|
|
Use Custom Properties in Forms to Standardize & Speed up RADArticle #2 in Series - RAD Tips | | You can use Custom Properties and Enums in Window Forms to enforce standards, speed coding, and make your code more readable. This is the second article in a series of articles on tips for Rapid Application Development in Visual Studio .NET, whether you are developing in VB.NET or C#. See my first article on Visual Inheritance.
Windows Forms are created with certain base properties. In .NET (C# and VB.NET), you can add your own properties to your forms. Using Attributes can cause them to be visible in the Forms Properties box, just like any intrinsic property. In this article, I will show three custom properties that you might want to add to your forms to standardize event handling functionality in your forms. The examples that I am using for this article will address three problems that I encounter in almost every Windows Form that has any appreciable logic in it. I will create the properties and then discuss the reason for them and their usage.
First, I will create three Enums to provide Intellisense, which makes your code much more readable. By the way, you can place the Enums above the Class definition line and save yourself one level of Intellisense.
Public Enum State
Loading
Loaded
Closing
End Enum
Public Enum Modified
Clean
Dirty
End Enum
Public Enum HandleEvents
[Default]
Busy
Noise
End Enum
|
Next, I will add three Private variables that will utilize these Enums.
Private _FormState As State
Private _FormChanged As Modified
Private _FormEventHandling As HandleEvents
|
Next, I will create the Public Properties for these events.
<Browsable(True), _
Description("Tells the Load State of the form")> _
Public Property FormState() As State
Get
Return _FormState
End Get
Set(ByVal Value As State)
_FormState = Value
End Set
End Property
<Browsable(True), _
Description("Tells if control contents have been modified")> _
Public Property FormChanged() As Modified
Get
Return _FormChanged
End Get
Set(ByVal Value As Modified)
_FormChanged = Value
End Set
End Property
<Browsable(True), _
Description("Tells whether to ignore or process events")> _
Public Property FormEventHandling() As HandleEvents
Get
Return _FormEventHandling
End Get
Set(ByVal Value As HandleEvents)
_FormEventHandling = Value
End Set
End Property
|
As stated previously, there are three specific problems that I normally face in any complex Windows Form. First, there is almost always some initialization code which must be done when any form is initially loaded, but I do not want to do it but once for each instantiation of the form. In VB6, I would have set a formLoading variable to True in the Form_Load event, checked it in the Activate event, and if not set, I would perform some initialization and then set the formLoading variable to False so that with any subsequent firing of the Activated event, I would not execute the Initialization code again. That VB6 type code is shown below:
Private formLoading As Boolean
|
Private Sub frmDialogTemplate_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
formLoading = True
End Sub
|
Private Sub frmDialogTemplate_Activated(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.Activated
If formLoading Then
' this code will only execute once
' perform initialization code here,
' connect to database, load grids, etc.
' then turn off formLoading so we dont execute again
formLoading = False
End If
End Sub
|
In VB.NET, I will use new methology, which was available in VB6, but not necessarily pushed. In the first place, I will encourage you to use the Forms Constructor in my next article on Event Firiing Order. But, to continue with the illustrationg at hand, here is how I would use the previously created property FormState doing it the .NET way.
Private Sub frmDialogTemplate_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
FormState = State.Loading
End Sub
Private Sub frmDialogTemplate_Activated(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.Activated
If FormState = State.Loading Then
' this code will only execute once
' perform initialization code here,
' connect to database, load grids, etc.
' then turn off formLoading so we dont execute again
FormState = State.Loaded
End If
End Sub
|
You can easily see that the .NET way is more readable, and Intellisense kicks in when I am referencing the FormState property.
Another great thing that you can do with Custom Properties is to make them show up in the Properties Box for the Form. If you take another look at the Public Properties, you will see that I have added <Browsable(True)> to the definition line of the properties. This causes the property to be displayed in the Properties Box as shown in Figure 1 below. Setting the Description attribute causes the description to show in the area below the properties.
There are some useful things to know about the Custom Public Properties. First, if you do not create a Set Acceptor in the Property Method, the property becomes ReadOnly and you cannot modify it at run-time. Second, if you omit the Get Acceptor, the property becomes Write Only and you cannot read it a run-time.
Figure 1 - Custom Properties in Property Box.

The second and third Custom Properties are designed to solve specific problems also. first, if you are designing a dialog where users can make changes, even if there is a Save button, you cannot assume that the user will click the Save button. If you close without saving changes, or at least without asking the user if they want to save the changes, you are going to have some unhappy campers in the user community. To solve this, I always have a Dirty flag, that gets set when the state of a control is changed. This code is illustrated below.
Private Sub TextBox1_TextChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles TextBox1.TextChanged
FormChanged = Modified.Dirty
End Sub
|
Next, I place code in the Form_Closing event to prompt the user about saving changes, if changes have been made. That code will be as follows.
Private Sub frmMyNewDialog_Closing(ByVal sender As Object, _
ByVal e As System.ComponentModel.CancelEventArgs) _
Handles MyBase.Closing
If FormChanged = Modified.Dirty Then
' implement save code or prompting here
End If
End Sub
|
When implementing the FormChanged event code, always make sure that you set the form to Modified.Clean after initialization, because many of the events will fire during initialization of the form and the Dirty flag will be set falsely.
The last problem I will solve with the third Custom Property, FormEventHandling, obviously has to do with handling events. Many times I programatically set the property of a CheckBox or TextBox, etc., at run-time. I know that setting a property of a control will normally cause some Change event to fire. However, I do not normally want to handle that event because my program, not the user, caused it. To keep from executing the event handling code, I will place some code in the event handler as shown below.
Private Sub TextBox1_TextChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles TextBox1.TextChanged
FormChanged = Modified.Dirty
' if the Noise flag is set, ignore the interrupt
If FormEventHandling = HandleEvents.Noise Then Exit Sub
' process the event here...
End Sub
|
Before I set the Text Property of the TextBox programatically, which will fire the TextChanged Event, I would set the Noise flag as shown below. After changing the Text Property, I will turn off the Noise flag.
' I am going to change the text of TextBox1, which
' will cause the change event to fire, so tell the
' handler to ignore the noise while I change the text
FormEventHandling = HandleEvents.Noise
TextBox1.Text = "New Text"
FormEventHandling = HandleEvents.Default
|
This article has illustrated the myriad of things that you can do with Custom Properties. I hope that I have given you some food for thought if you do not already use them.
Top of Page |
|