Introduction
This article shall describe the construction of a custom control used to display
currency values. The control is intended
for use in Win Forms application development. The
purpose of control is to allow the user to enter numeric values which are
subsequently converted to and displayed as currency (as is indicated in figure 1
(below)).
The user of the
control may drop any number of the currency controls into a form to display
numeric values as currency; the control itself is merely an extended textbox. By
placing the code necessary to support the functionality into the format of a
custom control, the need for writing the code necessary to support the display
of currency for each textbox used is eliminated.
Figure 1: The VB Currency Control in
Use.
Getting Started
The solution contains
two projects. The first project is called "UseCurrencyControl" and the second
project is called "CurrencyControl_VB". The first project is provided to
demonstrate use of the control in a Win Forms application. The second project
contains the actual custom control which is called "CurrencyText".
Figure 2: Solution Explorer with
Both Projects Visible.
The Custom Control Project
Code: Currency
Text Control
The custom control's code contains all of the necessary methods used to restrict
user input and to display the values into a textbox as a currency value. The
control contains only the default imports as shown in the following:
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Text
Imports System.Windows.Forms
Public Class CurrencyText
Inherits TextBox
Following the imports statements the class declaration is configured to inherit
from the standard textbox control. By
inheriting from the textbox control, all of the functionality of the control is
included in the custom control. After
declaring the class, the next section of code is used to declare a private
member variable which, through a public property, is used to store the current
dollar value. Maintaining the dollar
value as an internal variable is necessary to support edits to the underlying
value after the value has been converted to a formatted string. It
further allows the user to perform calculations against this value when, for
example, the contents of multiple controls are added together. Note
that, in the constructor show in the following code, the controls causes
validation property is set to true.
Refer to the annotation for a description of the intent of each section of the
sample code.
''' <summary>
''' Declare a local variable used to contain
''' the current dollar value
''' </summary>
''' <remarks></remarks>
Private mDollarValue As Decimal
''' <summary>
''' Declare public property used to get/set current dollar value
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property DollarValue() As Decimal
Get
Return mDollarValue
End Get
Set(ByVal value As Decimal)
mDollarValue
= value
End Set
End Property
''' <summary>
''' Default constructor; sets dollar value to zero
''' when control is created
''' </summary>
''' <remarks></remarks>
Public Sub New()
'
This call is required by the Windows Form Designer.
InitializeComponent()
Me.CausesValidation
= True
DollarValue
= 0
End Sub
''' <summary>
''' Default OnPaint event
''' </summary>
''' <param
name="e"></param>
''' <remarks></remarks>
Protected Overrides Sub OnPaint(ByVal e As
System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
End Sub
The next section of code in the control is used to handle the keypress event. The
purpose of the keypress event handler is to limit the user to keying in numbers
and decimal points. The handler also
allows the users to use the backspace button and other control characters when
editing the contents of the currency text box. This
code also limits the user to entering in only a single decimal point. As
shown below, the event handler will also prevent the user from keying in a
decimal point as the first character in the string; this may or may not be
necessary and you can comment out this part if that functionality is not
desired.
''' <summary>
''' Key press event handler or text; limits user inputs to numbers,
''' a single decimal point, and control characters to permit edits
''' to the contents of the box (e.g., using the backspace key)
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub CurrencyText_KeyPress(ByVal sender As System.Object,
_
ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles
MyBase.KeyPress
'
allows only numbers, decimals and control characters
If Not Char.IsDigit(e.KeyChar) And Not Char.IsControl(e.KeyChar)
_
And e.KeyChar
<> "." Then
e.Handled
= True
End If
'
allows only a single decimal point
If e.KeyChar
= "." And Me.Text.Contains(".") Then
e.Handled
= True
End If
'
denies entry of point without leading value (e.g., zero)
'
disable this if you don't want to insist on a leading zero
'
or other value
If e.KeyChar
= "." And Me.Text.Length
< 1 Then
e.Handled
= True
End If
End Sub
After the keypress event handler, the next section of code is used to handle the
"validated" event for the control. This
handler will attempt to convert the contents of the textbox to a properly
formatted currency value whenever the control is validated (also recall that in
the constructor, the control's causes validation property was set to true).
''' <summary>
''' Update display to show decimal as currency whenver it is validated
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub CurrencyText_Validated(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles MyBase.Validated
Try
Dim dTmp As Decimal
dTmp
= Convert.ToDecimal(Me.Text.ToString())
Me.Text
= dTmp.ToString("C")
Catch
'
skip it
End Try
End Sub
Next up is the code
used to handle the control's click event. In
the case of this control, the intent is to convert the value displayed in the
textbox back to the actual underlying control value as it stored in control (the
actual decimal value). If
the current dollar value property is zero, the application will clear the
textbox (so that the user does not end up with the cursor trailing the zero). If
the dollar value property does contain a value, the cursor is positioned at the
end of that value.
''' <summary>
''' Revert back to the display of numbers only
''' whenever the user clicks in the box for
''' editing purposes
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub CurrencyText_Click(ByVal sender As System.Object,
_
ByVal e As System.EventArgs) Handles MyBase.Click
Me.Text
= DollarValue.ToString()
If Me.Text
= "0.00" Then
Me.Clear()
End If
Me.SelectionStart
= Me.Text.Length
End Sub
The next section of code after the click event handler is the code used to
handle the text changed event for the control. In
this instance, whenever the value in the control is changed, the dollar value
property is updated to hold the latest value. Since
all computations and edits are based upon the dollar value property, it is
necessary to constantly update this value to reflect the content of the text
box.
''' <summary>
''' Update the dollar value each time the value is changed
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub CurrencyText_TextChanged(ByVal sender As System.Object, ByVal
e As System.EventArgs) Handles MyBase.TextChanged
Try
Dim strValue
= Me.Text
If (Me.Text.Length
= 0) Then
DollarValue
= 0
Else
'
remove space and set allowed formatting
DollarValue
= Decimal.Parse(Me.Text.Replace("
", ""),
_
Globalization.NumberStyles.AllowThousands Or _
Globalization.NumberStyles.AllowDecimalPoint Or _
Globalization.NumberStyles.AllowCurrencySymbol)
End If
Catch
'
skip it for formatting
End Try
End Sub
Code: Use
Currency Control Test Project
This project is used to test the custom control. The
project contains a single Windows form. The
form contains four of the custom controls and a button. The
demo application is used to show the controls in use; the application allows the
user to enter three currency values and then, in a button click event handler,
the fourth value is calculated and displayed.
The code for this form is as follows: (refer
to the annotation for specific descriptions of the functionality).
''' <summary>
''' This form class is intended to demonstrate the use of the
''' CurrencyControl; it is not intended to serve as an actual
''' tax program although the Federal Government would likely be
''' very happy for people to use this program as the basis for
''' determining their tax liability - It is very likely that you will
''' experience a much happier tax return if you use TurboTax or TaxCut, or
''' if you hire the services of a tax specialist.
''' </summary>
''' <remarks></remarks>
Public Class Form1
''' <summary>
'''
Sum up the damages for this year and share the good news
'''
with the user
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub btnCalcTaxes_Click(ByVal sender As System.Object,
_
ByVal e As System.EventArgs) Handles btnCalcTaxes.Click
'
Need to know how much they earned, don't care if they paid any
'
taxes though
If Me.ctxWages.DollarValue
= 0.0 Then
MessageBox.Show("We
need to know how much you made last year,
really.", "Missing
Money")
Return
End If
'
Set some local variables of the correct type and
'
collect their values from the form
Dim decFedTax As Decimal =
ctxFedTax.DollarValue
Dim decStateTax As Decimal =
ctxStateTax.DollarValue
'
Do the math
Dim decDeductions As Decimal =
decFedTax + decStateTax
Dim decOwedAmount As Decimal =
ctxWages.DollarValue - decDeductions
'
Display the results - since the amount owed's textbox does not
'
get validated now, format the output so that it will immediately
'
display as currency
Me.ctxOwedAmount.Text
= decOwedAmount
ctxOwedAmount.Text
= decOwedAmount.ToString("C")
End Sub
''' <summary>
'''
Exit the application and close open forms
''' </summary>
''' <param
name="sender"></param>
''' <param
name="e"></param>
''' <remarks></remarks>
Private Sub btnExit_Click(ByVal sender As System.Object,
_
ByVal e As System.EventArgs) Handles btnExit.Click
Me.Dispose()
End Sub
End Class
Aside from the button click event handler, there was no additional code added to
the form to speak of. The button click
event handler adds the dollar value properties for the state and federal taxes
paid from the two custom controls used to collect those values; that total is
then subtracted from the amount earned which is in turn gathered from the custom
control used to collect the wages and tips. After
subtracting the taxes paid from the money made, the result is dropped into the
control used to show the amount due and the user is instructed to send in all of
the rest of their earning less the amount already paid in taxes. I
think the old 1040-EZ tax joke went something like, "How much did you make?",
"Send it in".
Summary.
This article was intended to demonstrate an approach to building a custom
control that could be used to display a decimal value as currency. By
incorporating the code necessary to support the display of a decimal value in
the format of currency into a custom control, the user may add any number of
currency controls to a form without rewriting the code contained in the custom
control for each instance of the control.