65.9K
CodeProject 正在变化。 阅读更多。
Home

使用自定义控件转换货币值

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.57/5 (6投票s)

2006年11月8日

7分钟阅读

viewsIcon

46440

downloadIcon

534

本文详细介绍了如何构建一个自定义的ASP.NET 2.0复合控件,用于将一种货币转换为另一种。

引言

本文详细介绍了如何构建一个自定义的ASP.NET 2.0复合控件,用于将一种货币转换为另一种。该控件会调用一个公共的Web服务来计算汇率,并使用从Web服务返回的汇率来计算兑换货币的价值。

该控件的操作很简单,用户输入要兑换的金额,然后通过下拉列表设置兑换的货币类型和目标货币类型;一旦这三个值都设置完毕,用户就可以点击控件底部的“提交”按钮。提交后,控件将调用Web服务,并将两种货币格式传递给它;Web服务然后返回汇率。控件接着使用汇率计算出兑换成新货币类型后的价值。最后,所有这些信息都会显示给最终用户。

作为一个复合控件,它可以被添加到任何网页中,无需额外的编码即可为页面提供该功能。

演示控件库仅包含一个控件;该控件本身通过使用ASP.NET 2.0控件状态来维护状态。控件的渲染保持简单。随附的文件还包括一个样本网站,该网站仅用作演示控件的容器。

控件在网页上的使用示例显示在下图(图1)中。

图 1:货币转换自定义控件的使用

入门

此项目包含的文件包括一个Web控件库项目和一个演示Web网站。要开始,请打开包含的zip文件并将两个项目安装到您的文件系统中。打开IIS并为Web应用程序创建一个虚拟目录。打开Visual Studio 2005中的解决方案,并进行必要的更改,将两个项目添加到解决方案中。配置正确后,您的解决方案资源管理器应显示这些项目、引用和文件。

图 2:显示Web应用程序和控件库的解决方案资源管理器

在检查解决方案时,请注意“CurrencyConvertControl”控件库仅包含一个控件,该控件名为“MoneyChanger”。该项目还包含一个指向http://www.webservicex.net站点的Web引用;这个公共站点提供并支持用于计算多种货币之间汇率的免费Web服务。

Web应用程序仅包含一个Web页面(default.aspx),并包含对“CurrencyConvertControl”动态链接库的引用。

Web应用程序用作测试自定义控件的容器。

代码:MoneyChanger

“MoneyChanger”自定义复合控件旨在在初始化时从Web服务检索信息,并使用该信息显示当前的汇率,以及在货币类型之间进行转换后计算货币的转换值。该控件支持大约150种不同的货币类型。

Web服务接受两个参数:要兑换的货币类型和要兑换到的货币类型;响应请求时,服务将返回一个双精度数,其中包含两种货币之间的汇率,并且计算结果敏感于货币转换的方向(例如,欧元兑美元的结果将不等于美元兑欧元)。

在检查代码时,请注意类中仅包含默认的导入。该类本身继承自CompositeControl类。

Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Text
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls

<ToolboxData("<{0}:MoneyChanger " & _ 
    "runat=server></{0}:MoneyChanger>")> _
Public Class MoneyChanger
    Inherits CompositeControl

在类声明之后,创建了一个名为“Declarations”的区域,该区域内声明了控件中使用的所有对象。可序列化结构用于维护控件状态;该结构包含控件使用的成员变量。除此之外,还声明了一个用于提交按钮的事件,创建了可序列化结构(CurrentProperties)的一个实例,声明了使用的每个控件,并声明了Web服务。

#Region "Declarations"

    Public Event Change(ByVal Sender As Object, ByVal E As EventArgs)
    Private mCurrentProps As New CurrentProperties
    Public ddlFromCurrency As DropDownList
    Public ddlToCurrency As DropDownList
    Public txtExchangeRate As TextBox
    Public txtAmountToExchange As TextBox
    Public txtExchangedAmount As TextBox
    Public btnSubmit As Button
    Private mXchange As net.webservicex.www.CurrencyConvertor

    <Serializable()> _
    Private Structure CurrentProperties
        Dim mFromCurr As Integer
        Dim mToCurr As Integer
        Dim mResult As Double
        Dim mAmountToExchange As Decimal
        Dim mExchangedAmount As Decimal
    End Structure

#End Region

变量声明之后,定义了另一个区域(Methods),该区域包含驱动控件的代码。

Methods区域中包含的代码如下:

#Region "Methods"

    Private Sub MoneyChanger_Init(ByVal sender As Object, _
            ByVal e As System.EventArgs) Handles Me.Init

        ' required to enable control state
        Page.RegisterRequiresControlState(Me)

    End Sub

控件中使用的第一个子程序是初始化事件处理程序;该处理程序用于设置Page属性,以便使用ASP.NET 2.0控件状态。Methods区域中的下一个子程序是按钮单击事件处理程序,用于处理提交按钮的单击事件。此子程序连接到Web服务,并根据用户提供的货币选择请求汇率。处理程序还根据两种货币类型之间的汇率执行将货币金额转换所需的计算。一旦收到汇率并计算出转换值,处理程序将更新显示给用户的信息。

Private Sub btnSubmit_Click(ByVal Sender As Object, ByVal E As EventArgs)

    'update the to and from currency values from the drop down lists
    SetFromCurrency()
    SetToCurrency()

    'capture the amount to be exchanged into a property
    AmountToExchange = Convert.ToDecimal(txtAmountToExchange.Text)

    ' instance and call the web service to get the conversion rate
    mXchange = New net.webservicex.www.CurrencyConvertor
    Dim dblTemp As Double
    dblTemp = mXchange.ConversionRate(FromCurrency, ToCurrency)
    Result = dblTemp.ToString()

    'update the exchange rate textbox 
    'to show the returned change rate
    txtExchangeRate.Text = Result
    txtExchangeRate.Enabled = True

    'calculate the value of the money once 
    'converted to the new currency
    'type and then store it into a property
    ExchangedAmount = AmountToExchange * Result

    'convert the ExchangedAmount variable to the proper format
    'and display it in the control
    txtExchangedAmount.Text = ExchangedAmount.ToString("##.00")
    txtExchangedAmount.Enabled = True

    OnChange(EventArgs.Empty)

End Sub

接下来的三个子程序简短且简单。

Protected Sub OnChange(ByVal E As EventArgs)
    RaiseEvent Change(Me, E)
End Sub


Protected Overrides Function SaveControlState() As Object
    Return Me.mCurrentProps
End Function


Protected Overrides Sub LoadControlState(ByVal savedState As Object)
    mCurrentProps = New CurrentProperties
    mCurrentProps = CType(savedState, CurrentProperties)
End Sub

OnChange用于引发一个事件;这是处理提交按钮单击事件的代码的一部分。另外两个子程序用于在回发之间保存和加载控件状态。

接下来是重写的CreateChildControls子程序;在此子程序中,所有控件都被实例化、填充并添加到控件中。注释描述了子程序的每个部分。

Protected Overrides Sub CreateChildControls()

    ' create the dropdown list used to display
    ' the from currency types
    ddlFromCurrency = New DropDownList
    ddlFromCurrency.ID = "ddlFromCurrency"
    'populates DDL with currency types
    LoadDropDownList(ddlFromCurrency)
    Me.Controls.Add(ddlFromCurrency)

    ' create the dropdown list used to display
    ' the to currency types
    ddlToCurrency = New DropDownList
    ddlToCurrency.ID = "ddlToCurrency"
    'populates DDL with currency types
    LoadDropDownList(ddlToCurrency)
    Me.Controls.Add(ddlToCurrency)

    ' create the textbox used to display
    ' the exchange rate
    txtExchangeRate = New TextBox
    txtExchangeRate.ID = "txtExchangeRate"
    txtExchangeRate.Enabled = False
    'display result value if any
    txtExchangeRate.Text = Me.mCurrentProps.mResult
    Me.Controls.Add(txtExchangeRate)

    ' create the textbox used to capture and display
    ' the number of units of one type of currency
    ' to convert into another type of currency.
    ' Defaults to enabled = false since it will
    ' not contain any data and the user won't manually
    ' enter this calculated value
    txtAmountToExchange = New TextBox
    txtAmountToExchange.ID = "txtAmountToExchange"
    txtAmountToExchange.Text = _
         Me.mCurrentProps.mAmountToExchange
    Me.Controls.Add(txtAmountToExchange)

    ' create the textbox used to display the exchange
    ' rate calculated and returned by the web service
    txtExchangedAmount = New TextBox
    txtExchangedAmount.ID = "txtExchangedAmount"
    txtExchangedAmount.Enabled = False
    txtExchangedAmount.Text = _
         Me.mCurrentProps.mExchangedAmount
    Me.Controls.Add(txtExchangedAmount)

    ' creats the submit button and assigns it a handler
    btnSubmit = New Button
    btnSubmit.Text = "Submit"
    AddHandler btnSubmit.Click, _
               AddressOf btnSubmit_Click
    Me.Controls.Add(btnSubmit)

End Sub

接下来是用于设置ToCurrencyFromCurrency属性的子程序,这些属性用于显示下拉列表中用户选择的值。这些是控件内部使用的属性,代表传递给Web服务的“to”和“from”货币参数。由于Web服务用于表示货币类型的枚举存在一些问题,因此有必要将每个下拉列表项的值填充为代表枚举值的整数。To-和FromCurrency属性实际上设置为读取值,而不是下拉列表中的索引或文本。

Private Sub SetFromCurrency()
    FromCurrency = ddlFromCurrency.SelectedValue
End Sub

Private Sub SetToCurrency()
    ToCurrency = ddlToCurrency.SelectedValue
End Sub

下一个子程序用于填充用于显示“to”和“from”货币类型的下拉列表;有大约150种不同类型,所以我不会显示整个子程序,因为它大部分是重复的。子程序接受下拉列表控件作为参数,并在每次调用此子程序时清除并填充下拉列表。

Private Sub LoadDropDownList(ByVal ddl As DropDownList)

    ddl.Items.Clear()

    ddl.Items.Add("AED-UAE Dirham")
    ddl.Items(0).Value = 139
    ddl.Items.Add("AFA-Afghanistan Afghani")
    ddl.Items(1).Value = 0
    ddl.Items.Add("ALL-Albanian Lek")
    ddl.Items(2).Value = 1

代码中定义的下一个区域称为“Properties”;本节包含控件使用的属性。在这种情况下,所有属性都声明为私有,因为它们都仅由控件内部使用;这可以防止在设计时在IDE中显示这些属性。如果您希望这些属性出现在属性编辑器中,您需要将它们转换为公共属性,并应用适当的属性(类别、可浏览、描述等)以提供足够的设计时支持。请注意,在每个属性中都包含了对EnsureChildControlsSaveControlState的调用。这两个调用都是为了使控件内的控件保持最新,并根据属性的变化来维护控件状态。

#Region "Properties"

    Private Property Result() As Double
        Get
            EnsureChildControls()
            Return mCurrentProps.mResult
        End Get
        Set(ByVal value As Double)
            EnsureChildControls()
            mCurrentProps.mResult = value
            SaveControlState()
        End Set
    End Property

    Private Property FromCurrency() As Integer
        Get
            EnsureChildControls()
            Return mCurrentProps.mFromCurr
        End Get
        Set(ByVal value As Integer)
            EnsureChildControls()
            mCurrentProps.mFromCurr = value
            SaveControlState()
        End Set
    End Property


    Private Property ToCurrency() As Integer
        Get
            EnsureChildControls()
            Return mCurrentProps.mToCurr
        End Get
        Set(ByVal value As Integer)
            EnsureChildControls()
            mCurrentProps.mToCurr = value
            SaveControlState()
        End Set
    End Property


    Private Property AmountToExchange() As Decimal
        Get
            EnsureChildControls()
            Return mCurrentProps.mAmountToExchange
        End Get
        Set(ByVal value As Decimal)
            EnsureChildControls()
            mCurrentProps.mAmountToExchange = value
            SaveControlState()
        End Set
    End Property


    Private Property ExchangedAmount() As Decimal
        Get
            EnsureChildControls()
            Return mCurrentProps.mExchangedAmount
        End Get
        Set(ByVal value As Decimal)
            EnsureChildControls()
            mCurrentProps.mExchangedAmount = value
            SaveControlState()
        End Set
    End Property

#End Region

用于渲染控件的代码非常简单;HtmlTextWriter用于定义一个表并设置其特征(在此示例中是单元格填充),表的每一行包含两个单元格,一个标签及其关联的控件被放置在每个单元格中。一旦所有数据都写入表中,就会渲染结束标签,控件就完成了。

当然,您可以通过修改HtmlTextWriter定义的HTML来更改表的配置或删除从Web服务返回的某些数据。RenderContents子程序被重写,HTML通过HtmlTextWriter在此子程序中进行格式化。

#Region "Rendering"

Protected Overrides Sub RenderContents(ByVal _
                    output As HtmlTextWriter)

    Try
        output.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "3")
        output.RenderBeginTag(HtmlTextWriterTag.Table)

        ' Amount to Exchange
        output.RenderBeginTag(HtmlTextWriterTag.Tr)
        output.RenderBeginTag(HtmlTextWriterTag.Td)
        output.AddAttribute(HtmlTextWriterAttribute.For, _
                            txtAmountToExchange.ClientID)
        output.RenderBeginTag(HtmlTextWriterTag.Label)
        output.Write("Amount to Exchange: ")
        output.RenderEndTag()
        output.RenderBeginTag(HtmlTextWriterTag.Td)
        output.AddStyleAttribute(HtmlTextWriterStyle.FontFamily, _
                                 Me.Font.Name)
        output.AddAttribute(HtmlTextWriterAttribute.Size, _
                            Me.Font.Size.ToString())
        txtAmountToExchange.RenderControl(output)
        output.RenderEndTag()
        output.RenderEndTag()
        output.RenderEndTag()

        ' from currency
        output.RenderBeginTag(HtmlTextWriterTag.Tr)
        output.RenderBeginTag(HtmlTextWriterTag.Td)
        output.AddAttribute(HtmlTextWriterAttribute.For, _
                            Me.ddlFromCurrency.ClientID)
        output.RenderBeginTag(HtmlTextWriterTag.Label)
        output.Write("Convert from this currency: ")
        output.RenderEndTag()
        output.RenderBeginTag(HtmlTextWriterTag.Td)
        output.AddStyleAttribute(_
              HtmlTextWriterStyle.FontFamily, Me.Font.Name)
        output.AddAttribute(HtmlTextWriterAttribute.Size, _
                                   Me.Font.Size.ToString())
        ddlFromCurrency.RenderControl(output)
        output.RenderEndTag()
        output.RenderEndTag()
        output.RenderEndTag()

        ' to currency
        output.RenderBeginTag(HtmlTextWriterTag.Tr)
        output.RenderBeginTag(HtmlTextWriterTag.Td)
        output.AddAttribute(HtmlTextWriterAttribute.For, _
                              Me.ddlToCurrency.ClientID)
        output.RenderBeginTag(HtmlTextWriterTag.Label)
        output.Write("Convert to this currency: ")
        output.RenderEndTag()
        output.RenderBeginTag(HtmlTextWriterTag.Td)
        output.AddStyleAttribute(_
            HtmlTextWriterStyle.FontFamily, Me.Font.Name)
        output.AddAttribute(HtmlTextWriterAttribute.Size, _
                            Me.Font.Size.ToString())
        ddlToCurrency.RenderControl(output)
        output.RenderEndTag()
        output.RenderEndTag()
        output.RenderEndTag()

        ' exchange rate
        output.RenderBeginTag(HtmlTextWriterTag.Tr)
        output.RenderBeginTag(HtmlTextWriterTag.Td)
        output.AddAttribute(HtmlTextWriterAttribute.For, _
                            Me.txtExchangeRate.ClientID)
        output.RenderBeginTag(HtmlTextWriterTag.Label)
        output.Write("Exchange Rate: ")
        output.RenderEndTag()
        output.RenderBeginTag(HtmlTextWriterTag.Td)
        txtExchangeRate.Text = mCurrentProps.mResult
        output.AddStyleAttribute(_
             HtmlTextWriterStyle.FontFamily, Me.Font.Name)
        output.AddAttribute(HtmlTextWriterAttribute.Size, _
                            Me.Font.Size.ToString())
        txtExchangeRate.RenderControl(output)
        output.RenderEndTag()
        output.RenderEndTag()
        output.RenderEndTag()

        ' Exchanged Amount
        output.RenderBeginTag(HtmlTextWriterTag.Tr)
        output.RenderBeginTag(HtmlTextWriterTag.Td)
        output.AddAttribute(HtmlTextWriterAttribute.For, _
                            txtExchangedAmount.ClientID)
        output.RenderBeginTag(HtmlTextWriterTag.Label)
        output.Write("Amount After Exchange: ")
        output.RenderEndTag()
        output.RenderBeginTag(HtmlTextWriterTag.Td)
        output.AddStyleAttribute(_
           HtmlTextWriterStyle.FontFamily, Me.Font.Name)
        output.AddAttribute(HtmlTextWriterAttribute.Size, _
                            Me.Font.Size.ToString())
        txtExchangedAmount.RenderControl(output)
        output.RenderEndTag()
        output.RenderEndTag()
        output.RenderEndTag()

        ' submit button
        output.RenderBeginTag(HtmlTextWriterTag.Tr)
        output.RenderBeginTag(HtmlTextWriterTag.Td)
        output.AddAttribute(HtmlTextWriterAttribute.For, _
                            Me.btnSubmit.ClientID)
        output.AddStyleAttribute(HtmlTextWriterStyle.FontFamily, _
                                 Me.Font.Name)
        output.AddAttribute(HtmlTextWriterAttribute.Size, _
                            Me.Font.Size.ToString())
        output.RenderBeginTag(HtmlTextWriterTag.Label)
        output.Write("Retrieve Exchange Rate: ")
        output.RenderEndTag()
        output.RenderBeginTag(HtmlTextWriterTag.Td)
        output.AddStyleAttribute(HtmlTextWriterStyle.FontFamily, _
                                 Me.Font.Name)
        output.AddAttribute(HtmlTextWriterAttribute.Size, _
                            Me.Font.Size.ToString())
        btnSubmit.RenderControl(output)
        output.RenderEndTag()
        output.RenderEndTag()
        output.RenderEndTag()

        output.RenderEndTag()

    Catch

        output.Write("Money Changer Custom Control")

    End Try

End Sub

#End Region

代码:演示站点的默认页面

演示站点中包含的default.aspx页面仅用作控件的测试容器。该页面仅包含一行文本,用于描述页面和控件本身。在浏览器中显示default.aspx页面将能够测试该控件。

摘要

此项目旨在描述一个有用且易于构建的自定义复合控件。虽然此演示仅限于描述Money Changer自定义复合控件,但此处应用的方法也适用于各种其他自定义复合控件。它确实提供了一个在自定义控件中消耗Web服务的示例,并且该方法可以应用于显示任何Web服务的信息。此演示中使用的Web服务不受我的控制,因此我无法预测其寿命。

© . All rights reserved.