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






4.57/5 (6投票s)
2006年11月8日
7分钟阅读

46440

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
接下来是用于设置ToCurrency
和FromCurrency
属性的子程序,这些属性用于显示下拉列表中用户选择的值。这些是控件内部使用的属性,代表传递给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中显示这些属性。如果您希望这些属性出现在属性编辑器中,您需要将它们转换为公共属性,并应用适当的属性(类别、可浏览、描述等)以提供足够的设计时支持。请注意,在每个属性中都包含了对EnsureChildControls
和SaveControlState
的调用。这两个调用都是为了使控件内的控件保持最新,并根据属性的变化来维护控件状态。
#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服务不受我的控制,因此我无法预测其寿命。