WEBINAR:
On-Demand
Building the Right Environment to Support AI, Machine Learning and Deep Learning
Extending Windows Forms Controls
Using Visual Studio 2005, create a new Windows application and name it WindowsControls. This Windows application project will act as the host for the controls that you will be extending shortly.
Now, add a new Class Library project (File | Add | New Project…) to the current solution and name the project EnhancedTextBox.
As you are going to extend a Windows Forms control in this project (specifically the TextBox control), add a reference to System.Windows.Forms (right-click on the EnhancedTextBox project name in Solution Explorer and select Add Reference…).
Import the following namespaces:
Imports System.Windows.Forms
Imports System.ComponentModel
Next, define the following enumerations (in bold) for the different types of casings, filters, and the different levels of precisions:
Imports System.Windows.Forms
Imports System.ComponentModel
Public Enum Cases
Mixed
UpperOnly
LowerOnly
End Enum
Public Enum FilterTypes
None
IntegerNumeric
DecimalNumeric
AlphabetsOnly
Alphanumeric
End Enum
Public Enum Precisions
None
OneDecimal
TwoDecimal
ThreeDecimal
End Enum
And since you are extending the TextBox control, you need to inherit the EnhancedTextBox class from System.Windows.Forms.TextBox:
Public Class EnhancedTextBox
Inherits System.Windows.Forms.TextBox
Declaring the Member Variables
You can now declare the member variables to store the filter type, casing, precision, as well as the regular expression as set by the user. Also, define an event so that when the validation fails, the user of the control can react appropriately:
<DefaultEvent("Err")> _
Public Class EnhancedTextBox
Inherits System.Windows.Forms.TextBox
'---member variables for filtering---
Private _filterType As FilterTypes = FilterTypes.None
Private _casing As Cases = Cases.Mixed
Private _precision As Precisions = Precisions.None
'---member variables for regular expression validation---
Private _regex As String
Private _regexErrMsg As String
'---event handler for error---
<Category("Custom Properties"), _
DescriptionAttribute("Error event handler.")> _
Public Event Err(ByVal str As String)
Notice that I have marked the class with a DefaultEventAttribute that specifies the Err as the default event handler. I have also marked the Err event with the CategoryAttribute to associate it with the Custom Properties category in the Properties window (you will see this in action later). The DescriptionAttribute specifies the description for this event.
Declaring the Properties
You will next declare the various properties that allow the user to control the types of filter, precisions, and casing they want, as well as enter the regular expression to use for custom validation.
The Precision property specifies the number of decimal places with which to format the text input:
'---property for setting precision---
<Category("Custom Properties"), _
DescriptionAttribute("Number of decimal places.")> _
Public Property Precision() As Precisions
Get
Return _precision
End Get
Set(ByVal value As Precisions)
_precision = value
End Set
End Property
The EnforceCasing property indicates if the character entered should automatically be converted to upper or lower casing:
'---property for enforcing casing---
<Category("Custom Properties"), _
DescriptionAttribute("Specifies if the characters " & _
"typed need to be converted to the specified case.")> _
Public Property EnforceCasing() As Cases
Get
Return _casing
End Get
Set(ByVal value As Cases)
_casing = value
End Set
End Property
The FilterType property specifies the types of characters allowed for entry:
'---property for setting filter types---
<Category("Custom Properties"), _
DescriptionAttribute("Specifies the type of filter to apply.")> _
Public Property FilterType() As FilterTypes
Get
Return _filterType
End Get
Set(ByVal value As FilterTypes)
_filterType = value
End Set
End Property
The RegularExpression property allows the user to set the regular expression to be used for custom validation:
'---property for setting the regular expression---
<Category("Custom Properties"), _
DescriptionAttribute("Regular expression for custom validation.")> _
Public Property RegularExpression() As String
Get
Return _regex
End Get
Set(ByVal value As String)
_regex = value
End Set
End Property
And finally, the RegularExpressionErrorMessage property allows the user to specify the error message to display in a balloon should the regular expression validation fail:
'---property for error message to display if regular expresson
' validation fails---
<Category("Custom Properties"), _
DescriptionAttribute("Error message for regular expression " & _
"validation.")> _
Public Property RegularExpressionErrorMessage() As String
Get
Return _regexErrMsg
End Get
Set(ByVal value As String)
_regexErrMsg = value
End Set
End Property
Servicing the Events
The final step is to service the various events associated with the TextBox control. To ensure that users can enter only the characters specified by the filter, you can service the KeyPress event of the TextBox control. The KeyPress event is fired whenever the user presses a key when the focus is on the TextBox control. This is the event to service so that only the allowed characters/digits are allowed to be shown in the TextBox control. The code for the KeyPress event is shown in
Listing 1.
Here, you check for various types of characters that the user may enter. If an invalid character is detected, the e.Handled property is set to True and the character will not be added to the TextBox. The IsControl() method checks to see if a character entered is a control character (such as Tab, Carriage Return, BackSpace, etc). It is important that you check for control characters. Why? One good example is the BackSpace character. If the BackSpace character is ignored in the KeyPress event, then the user might not be able to erase a character entered in a TextBox control by using the BackSpace key. That would be bad user interface design.
While servicing the KeyPress event can prohibit users from entering illegal characters, you still need to do some more work in another eventthe LostFocus event. The LostFocus event is fired when the focus is transferred from the TextBox control to somewhere else, such as pressing the Tab key to navigate to the next control.
A very important task you need to perform in this event is to validate the content of the TextBox control. This is because illegal characters can still seep into the control by methods other than direct entry through the keyboard; a user could assign the value of the TextBox control programmatically or paste (Ctrl-V) illegal characters into a TextBox control. For example, if you set a TextBox control with the IntegerNumeric filter, you are still able to programmatically assign a decimal numeric value to it through code. In this case, the KeyPress event cannot be used to restrict the assignment. Hence, in the LostFocus event you need to perform the various types of validation to ensure that the value in the TextBox control conforms to the specified filter. The code for the LostFocus event is shown in Listing 2.
The ShowErrorBalloon() method displays a message in a balloon using the ToolTip control:
Public Sub ShowErrorBalloon(ByVal str As String)
Dim toolTip1 As New ToolTip
With toolTip1
.IsBalloon = True
.Show(str, Me, 10, -40, 2000)
End With
End Sub