Walkthrough: Authoring a User Control with Visual Basic .NET
User controls provide a means by which custom graphical interfaces can be created and reused. A user control is essentially a component with a visual representation. As such, it might consist of one or more Windows Forms controls, components, or blocks of code that can extend functionality by validating user input, modifying display properties, or performing other tasks required by the author. User controls can be placed on Windows Forms in the same manner as other controls. In the first part of this walkthrough, you create a simple user control called ctlClock. In the second part of the walkthrough, you extend the functionality of ctlClock through inheritance.
Creating the Project
When you create a new project, you specify its name to set the root namespace, assembly name, and project name, and ensure that the default component will be in the correct namespace.
To create the ctlClockLib control library and the ctlClock control
- On the File menu, point to New and then select Project to open the New Project dialog box.
- Select the Windows Control Library project template from the list of Visual Basic Projects, and type ctlClockLib in the Name box.
Note The Windows Control Library template is not available in the Standard Edition of Visual Basic .NET. For more information, see Visual Basic Standard Edition Features.
The project name, ctlClockLib, is also assigned to the root namespace by default. The root namespace is used to qualify the names of components in the assembly. For example, if two assemblies provide components named ctlClock, you can specify your ctlClock component using
ctlClockLib.ctlClock.In Solution Explorer, right-click UserControl1 and select View Code from the shortcut menu.
- Locate the Class statement,
Public Class UserControl1, and change UserControl1 to ctlClock to change the name of the component.Note Notice the Inherits statement immediately below the Class statement. By default, a user control inherits from the UserControl class provided by the system. The UserControl class provides functionality required by all user controls, and implements standard methods and properties.
- In Solution Explorer, click UserControl1, then in the Properties window, change the FileName property to ctlClock.vb.
- From the File menu, choose Save All to save the project.
Adding Windows Controls and Components to your User Control
A visual interface is an essential part of your user control. This visual interface is implemented by the addition of one or more Windows controls to the User Control Designer. In the following demonstration, you will incorporate Windows controls into your user control and write code to implement functionality.
To add a Label and a Timer to your user control
- In Solution Explorer, right-click ctlClock.vb, and then select View Designer from the shortcut menu.
- In the Toolbox, click the Windows Forms tab, and then double-click Label.
A label control named Label1 is added to your control on the User Control Designer.
- In the designer, click Label1. In the Properties window, set the following properties.
Property Change to Name lblDisplay Text (blank space) TextAlign MiddleCenter Font.Size 14
- In the Toolbox, click Windows Forms, and then double-click Timer.
Because a timer is a component, it has no visual representation at run time. It therefore does not appear with the controls on the User Control Designer, but rather in the component tray.
- In the component tray, click Timer1 and set the Interval property to 1000 and the Enabled property to True.
The Interval property controls the frequency with which the timer component ticks. Each time Timer1 ticks, it runs the code in the Timer1_Tick event. The interval represents the number of milliseconds between ticks.
- In the component tray, double-click Timer1 to go to the Timer1_Tick event for ctlClock.
- Modify the code so that it resembles the following code sample. Be sure to change the access modifier from Private to Protected:
Protected Sub Timer1_Tick(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles Timer1.Tick ' Causes the label to display the current time lblDisplay.Text = Format(Now, "hh:mm:ss") End Sub
This code will cause the current time to be shown in lblDisplay. Because the interval of Timer1 was set to 1000, this event will fire every thousand milliseconds, thus updating the current time every second.
- Modify the method to be overridable. For more information, see the next section of this topic, "Inheriting from a User Control".
' Visual Basic Protected Overridable Sub Timer1_Tick(ByVal sender As Object, ByVal _ e As System.EventArgs) Handles Timer1.Tick
- From the File menu, choose Save ctlClock to save the project.
Adding Properties to Your User Control
Your clock control now encapsulates a Label control and a Timer component, each with its own set of inherent properties. While the individual properties of these controls will not be accessible to subsequent users of your control, you can create and expose custom properties by writing the appropriate blocks of code. In the following section, you will add properties to your control that enable the user to change the color of the background and text.
To add a Property to your user control
- In Solution Explorer, right-click ctlClock.vb, and then click View Code from the shortcut menu.
The Code Editor for your control opens.
- Locate the
Inherits System.Windows.Forms.UserControlstatement. Beneath it, type:
Private colFColor as Color Private colBColor as Color
These statements create the private variables that you will use to store the values for the properties you are about to create.
- Type the following code beneath the variable declarations from step 2:
' Declares the name and type of the property. Property ClockBackColor() as Color ' Retrieves the value of the private variable colBColor. Get Return colBColor End Get ' Stores the selected value in the private variable colBColor, and ' updates the backcolor of the label control lblDisplay. Set(ByVal Value as Color) colBColor = Value lblDisplay.BackColor = ColBColor End Set End Property ' Provides a similar set of instructions for the forecolor. Property ClockForeColor() as Color Get Return colFColor End Get Set(ByVal Value as Color) colFColor = Value lblDisplay.ForeColor = ColFColor End Set End Property
The preceding code makes two custom properties, ClockForeColor and ClockBackColor, available to subsequent users of this control by invoking the
Propertystatement. The Get and Set statements provide for storage and retrieval of the property value, as well as code to implement functionality appropriate to the property.
- From the File menu, choose Save ctlClock.vb to save the project.
Testing Your Control
Controls are not stand-alone projects; they must be hosted in a container. In order to test your control, you must provide a test project within which it runs. In this section, you will build your control and test it in a Windows Form.
To build your control
- On the Build menu, click Build ctlClockLib.
To create a test project
- On the File menu, point to Add Project and then click New Project to open the Add New Project window.
- Click Windows Application, and in the Name box, type Test, and click OK.
- In Solution Explorer, right-click the References node for your test project. Click Add Reference to display the Add Reference dialog box.
- Click the tab labeled Projects. Your project will be listed under Project Name.
- Double-click your project.
Note that your project now appears in the Selected Components window.
After you have added your reference, you can place your control in your form.
To test your control
- In the Toolbox, click My User Controls, and then scroll down until the control icon representing ctlClock is displayed.
- Double-click the ctlClock icon.
A copy of your control is now added to your form. Note that it displays the current time and is updated each second.
- In the Toolbox, select the icon and move your mouse over your form.
- Hold down the left mouse button while moving the mouse across the form.
Another copy of your control is drawn onto the form. You can add as many copies of your timer to your form as you want.
- In the designer, click one of the instances of ctlClock.
The properties for this instance are displayed in the Properties window.
- In the Properties window, locate the ClockBackColor property, and then select the property to display the color palette.
- Choose a color by clicking it.
The background color of your control changes to the color you selected.
- Use a similar sequence of events to verify that the ClockForeColor property is functioning as expected.
In this section, you have seen how components and Windows controls can be combined with code and packaging to provide custom functionality in the form of a user control. You have learned to expose properties in your user control, and how to test your control after it is complete. In the next section you will learn how to construct an inherited user control using ctlClock as a base.
Inheriting from a User Control
In the previous section, you learned how to combine Windows controls, components, and code into reusable user controls. Your user control can now be used as a base upon which other controls can be built. The process of deriving a class from a base class is called inheritance. In this section, you will create a user control called ctlAlarmClock. This control will be derived from its parent control, ctlClock. You will learn to extend the functionality of ctlClock by overriding parent methods and adding new methods and properties.
Creating the Inherited Control
The first step in creating an inherited control is to derive it from its parent. This action creates a new control that has all of the properties, methods, and graphical characteristics of the parent control, but can also act as a base for the addition of new or modified functionality.
To create the inherited control
- In Solution Explorer, click ctlClockLib.
- From the Project menu, select Add Inherited Control.
The Add New Item window opens with Inherited User Control selected.
- In the Name box, type ctlAlarmClock.vb, and click Open.
The Inheritance Picker window appears.
- Under Component Name, double-click ctlClock.
- In Solution Explorer, browse the current projects. Note that a file called ctlAlarmClock has been added.
Adding the Alarm Properties
Properties are added to an inherited control in the same way they are added to a user control. You will now use the property declaration syntax to add two properties to your control: AlarmTime, which will store the value of the date and time the alarm is to go off, and AlarmSet, which will indicate whether or not the alarm is set.
To add Properties to your user control
- In Solution Explorer, right-click ctlAlarmClock and select View Code from the shortcut menu.
- Locate the
Inheritsstatement. Note that your control inherits from ctlClockLib.ctlClock. Beneath the
Inheritsstatement, type the following code:
Private dteAlarmTime As Date Private blnAlarmSet As Boolean ' These properties will be declared as public to allow future ' developers to access them. Public Property AlarmTime() As Date Get Return dteAlarmTime End Get Set(ByVal Value as Date) dteAlarmTime = Value End Set End Property Public Property AlarmSet() As Boolean Get Return blnAlarmSet End Get Set(ByVal Value as Boolean) blnAlarmSet = Value End Set End Property
Adding to the Graphical Interface of Your Control
Your inherited control has a visual interface that is identical to the control it inherits from. It possesses the same constituent controls as its parent control, but the properties of the constituent controls will not be available unless they were specifically exposed. You may add to the graphical interface of an inherited user control in the same manner as you would add to any user control. To continue adding to your alarm clock's visual interface, you will add a label control that will flash when the alarm is sounding.
To add the label control
- In Solution Explorer, right-click ctlAlarmClock and select View Designer from the shortcut menu.
The designer for ctlAlarmClock opens in the main window.
- Click the display portion of the control, and observe the Properties window.
Note that while all the properties are displayed, they are dimmed. This indicates that these properties are native to lblDisplay, and cannot be modified or accessed in the properties window. By default, controls contained in a user control are
Private, and their properties are not accessible by any means.Tip If you want subsequent users of your user control to have access to its internal controls, declare them asPublicorProtected. This will allow you to set and modify properties of controls contained within your user control by using the appropriate code.
- Add a Label control to your user control.
- Using the mouse, move the label control immediately beneath the display box. In the Properties window, set the following properties:
Property Setting Name lblAlarm Text Alarm Is Sounding! TextAlign Middle Center Visible false
Adding the Alarm Functionality
In the previous sections, you added properties and a control that will enable alarm functionality in your user control. In this section, you will add code to compare the current time to the alarm time, and if they are the same, to sound and flash an alarm. By overriding the Timer1_Tick method of ctlClock, and adding additional code to it, you will extend the capability of ctlAlarmClock while retaining all of the inherent functionality of ctlClock.
To override the Timer1_Tick method of ctlClock
- In the Code Editor, locate the
Private blnAlarmSet As Booleanstatement. Immediately beneath it, add the following statement:
Dim blnColorTicker as Boolean
- In the Code Editor, locate the
End Classstatement. It can be found at the bottom of the page.
- Just before the
End Classstatement, add the following code:
Protected Overrides Sub Timer1_Tick(ByVal sender As Object, ByVal e _ As System.EventArgs) ' Calls the Timer1_Tick method of ctlClock. MyBase.Timer1_Tick(sender, e) ' Checks to see if the Alarm is set. If AlarmSet = False Then Exit Sub End If ' If the date, hour and minute of the alarm time are the same as ' now, flash and Beep! If AlarmTime.Date = Now.Date And AlarmTime.Hour = Now.Hour And _ AlarmTime.Minute = Now.Minute Then ' Sounds an audible Beep Beep() ' Makes lblAlarmVisible, and changes the backcolor based on the ' value of blnColorTicker. The backcolor of the label will ' flash once per tick of the clock. lblAlarm.Visible = True If blnColorTicker = False Then lblAlarm.BackColor = Color.PeachPuff blnColorTicker = True Else lblAlarm.BackColor = Color.Plum blnColorTicker = False End If Else ' Once the alarm has sounded for a minute, the label is made ' invisible again. lblAlarm.Visible = False End If End Sub
The addition of this code accomplishes several tasks. The
Overrides statement directs the control to use this method in place of the method that was inherited from the base control. When this method is called, it calls the method it overrides by invoking the
Tick statement, ensuring that all of the functionality incorporated in the original control is reproduced in this control. It then runs additional code to incorporate the alarm functionality. A flashing label control will appear when the alarm is sounding, and an audible beep will be heard.
Note that since you are overriding an inherited event handler, you do not have to specify the event with the
Handles keyword. The event is already hooked up. All you are overriding is the implementation of the handler.
Your alarm clock control is almost complete. The only thing that remains is to implement a way to turn it off. To do this, we will add code to the lblAlarm_Click method.
To implement the shutoff method
- In Solution Explorer, right-click ctlAlarmClock.vb and click View Designer.
The designer opens.
- In the designer, double-click lblAlarm. The Code Editor opens to the
Protected Sub lblAlarm_Clickline.
- Modify this method so that it resembles the following:
Protected Sub lblAlarm_Click(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles lblAlarm.Click ' Turns off the alarm. AlarmSet = False ' Hides the flashing label. lblAlarm.Visible = False End Sub
- From the File menu, choose Save ctlAlarmClock.vb to save the project.
Testing Your Inherited Control
As with a standard user control, an inherited user control cannot stand alone and must be hosted in a form or other container. Since ctlAlarmClock has a greater depth of functionality, additional code is required to test it. In this section, you will write a simple program to test the functionality of ctlAlarmClock. You will write code to set and display the AlarmTime property of ctlAlarmClock, and will test its inherent functions.
To build and add your control to a test form
- In Solution Explorer, click ctlClockLib. On the Build menu, choose Build ctlClockLib.
- Add a new Windows Application project to the solution, and name it Test2.
- In Solution Explorer, right-click the References node for your test project. Click Add Reference to display the Add Reference window. Click the tab labeled Projects. The project ctlClockLib will be listed under Project Name. Double-click ctlClockLib, and note that it now appears in the Selected Components window.
- In the Toolbox, click My User Controls.
- Scroll down until the icon for ctlAlarmClock comes into view.
- Double-click ctlAlarmClock to add a copy of ctlAlarmClock to your form.
- Locate and double-click DateTimePicker to add a DateTimePicker control to your form, and add a Label control by double-clicking Label.
- Use the mouse to position the controls in a convenient place on the form.
- Set the properties of these controls as follows:
Control Property Value Label1 Text (leave blank) Name lblTest DateTimePicker1 Name dtpTest Format Time
- In the designer, double-click dtpTest.
The Code Editor opens to
Protected Sub dtpTest_ValueChanged.
- Modify the code so that it resembles the following:
Protected Sub dtpTest_ValueChanged(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles dtpTest.ValueChanged ctlAlarmClock1.AlarmTime = dtpTest.Value ctlAlarmClock1.AlarmSet = True lblTest.Text = "Alarm Time is " & Format(ctlAlarmClock1.AlarmTime, _ "hh:mm") End Sub
- In Solution Explorer, right-click Test2 and choose Set as StartUp Project from the shortcut menu.
- From the Debug menu, choose Start.
The test program starts. Note that the current time is updated in the ctlAlarmClock control, and that the starting time is shown in the DateTimePicker control.
- Click the DateTimePicker where the minutes of the hour are displayed.
- Using the keyboard, set a value for minutes that is one minute greater than the current time shown by ctlAlarmClock.
The time for the alarm setting is shown in lblTest.
- Wait for the displayed time to reach the alarm setting time.
When the displayed time reaches the time to which the alarm is set, the beep will sound and lblAlarm will flash. Turn off the alarm by clicking lblAlarm. You may now reset the alarm.
This walkthrough has covered a number of key concepts. You have learned to create a user control by combining controls and components into a user control container. You have learned to add properties to your control, and to write code to implement custom functionality. In the second section, you learned to extend the functionality of a given user control through inheritence, and to alter the functionality of host methods by overriding those methods.