In this month column, I will show you how to create your own custom controls by extending existing control with new properties, methods or events. For those of you who have created some using VB6, you will soon discover that the process is now more straightforward and that it requires a lot less code because of the inheritance.
Practically speaking, we will extend the textbox control to be a numeric only textbox with Min and Max values and accept validation with a regular expression.
Let's go!
So to start the creation of your own control, select Windows Control Library from the New Project dialog and name it MyOwnControls. This will create UserControl1.vb in MyOwnControls project and solution. Notice that a single project of that kind can host many controls of your own.
Change the (Name) property of your control from UserControl1 to MyOwnTextBox (from the Properties dialog) and rename UserControl1.vb to MyOwnTextBox.vb (by right-clicking UserControl1.vb from the Solution Explorer and selecting Rename). Now open the code editor of your control and change
Inherits System.Windows.Forms.UserControl
for
Inherits System.Windows.Forms.TextBox
If you stop here and compile what we have done so far, you will get just another working textbox! Our MyOwnTextBox already have everything it needs to be a textbox but that's not what we want!
For the purpose of the demo, add an ErrorProvider control (remember my February column?) to the MyOwnTextBox control (that will be used to display validation error).
Let's extend!
We will start by adding 3 properties to our textbox control: a min value, a max value and also a regular expression for validation.
Private mdblValueMax As Double Private mdblValueMin As Double Private mstrValidationExpression As String Property ValidationExpression() As String Get Return mstrValidationExpression End Get Set(ByVal Value As String) Try If Value <> "" Then Dim dummy As Boolean dummy = Regex.IsMatch("abcde", Value) End If mstrValidationExpression = Value Catch ex As Exception MessageBox.Show(ex.Message, _ "Invalid value for this property", _ MessageBoxButtons.OK, _ MessageBoxIcon.Error) End Try End Set End Property Property ValueMax() As Double Get Return mdblValueMax End Get Set(ByVal Value As Double) mdblValueMax = Value End Set End Property Property ValueMin() As Double Get Return mdblValueMin End Get Set(ByVal Value As Double) mdblValueMin = Value End Set End Property
Be warned that a public field cannot be used as a property (like you may have used in VB6). You have to write your own property procedure like in the previous example.
The constructor can now initialized some of the values. Find the New constructor and modify it to looks like this.
Public Sub New() MyBase.New() 'This call is required by the Windows Form Designer. InitializeComponent() 'Add any initialization after the InitializeComponent() call Me.ValueMin = 0 Me.ValueMax = 100 Me.ValidationExpression = "\d+" End Sub
We will now ensure that user inputs are valid.
Private Sub MyOwnTextBox_KeyPress(ByVal sender As Object, _ ByVal e As System.Windows.Forms.KeyPressEventArgs) _ Handles MyBase.KeyPress 'This code is pasted from a a Universal Thread question 'answered by Cathi Gero (January 28, 2003) Dim KeyAscii As Integer KeyAscii = Asc(e.KeyChar) Select Case KeyAscii Case 48 To 57, 8, 13 ' don't do anything Case 45 If InStr(Me.Text, "-") <> 0 Then KeyAscii = 0 End If If Me.SelectionStart <> 0 Then KeyAscii = 0 End If Case 46 If InStr(Me.Text, ".") <> 0 Then KeyAscii = 0 End If Case Else KeyAscii = 0 End Select If KeyAscii = 0 Then e.Handled = True Else e.Handled = False End If End Sub
We now need a method that can be called when validation is needed. This method will use the previously declared properties.
Function Validate() As Boolean ErrorProvider1.SetError(Me, "") 'Empty string not allowed If Me.Text = "" Then ErrorProvider1.SetError(Me, _ "Value cannot be left empty!") Return False End If 'Check min and max values If Me.ValueMin <> 0 Or Me.ValueMax <> 0 Then If Val(Me.Text) < Me.ValueMin Then ErrorProvider1.SetError(Me, _ "Value is less then the ValueMin!") Return False End If If Val(Me.Text) > Me.ValueMax Then ErrorProvider1.SetError(Me, _ "Value is higher then the ValueMax!") Return False End If End If If Me.ValidationExpression <> "" Then If Not Regex.IsMatch(Me.Text, _ Me.ValidationExpression) _ Then ErrorProvider1.SetError(Me, _ "Pattern not respected!") Return False End If End If Return True End Function
We now need to call this method when the content of the textbox changes.
Private Sub MyOwnTextBox_TextChanged(ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles MyBase.TextChanged Me.Validate() End Sub
Let's compile!
This task is simple. From the Build menu, select the Build MyOwnControls item and your done. The result of the compilation will create a file with a DLL extension; so don't search for the OCX.
Let's test!
The easiest way to test your new creation is to add another project to your current solution. To do this, right-click your solution, select Add and then New Project … . From the Add New Project dialog, select a Windows Application. Just like when you were using multiple projects in a group in VB6, you need to set your testing project as the startup project. From the Solution Explorer, right click your test project and select Set as Startup Project.
If you now go into the Toolbox, you should now find MyOwnTextBox (should be completely at the bottom). Double-click on it and an instance of your textbox will be drawn on the form.
The control appeared in the toolbox because you are using a single solution. When you create a new application without having your control into the same solution, you need to add it to your toolbox. To do so, right click on the toolbox and select "Customize Toolbox". When a dialog appears, click on the .NET Framework Components tab. Then click on Browse... and pick the MyOwnControls.DLL.
Now select your control instance on your form and look at the properties, you will discover that all intrinsic properties of the textbox are already there. Have we done something for this? Yes. We have inherited!
Let's dance!
This is only the beginning of creating your own user controls. But as you can see the basis is easy enough for you to rapidly start building your own collection of specialized user controls.