Simulating Control Arrays in VB.NET
Control arrays were a very useful construct in pre-.NET ("classic") versions of VB (i.e., VB6 and before), but are not supported in VB.NET. Many articles have been written to discuss this and to demonstrate how to simulate the functionality of control arrays in VB.NET. About.com has a set of articles on this, which can be viewed at http://visualbasic.about.com/od/usingvbnet/a/dykctrlarray7.htm.
For those not familiar with "Classic VB", some background about control arrays is in order:
Similar to arrays of variables, you could group a set of controls together as an array. The following facts applied to control arrays:
ControlName(Index)[.Property]
For example, to refer to the Text property of the first element of an array of textboxes called txtField, you would use:
txtField(0).Text
Private Sub txtField_GotFocus(Index As Integer)
txtField(Index).SelStart = 0 txtField(Index).SelLength = Len(txtField(Index).Text)
End Sub
|
While many approaches to implementing control array functionality in .NET involve using special classes or collections, the approach presented here does not.
If I wanted a “control array” of four labels, I would do the following:
In design mode, place four labels on my form, and name them all the same, except that the last character(s) of the name would serve as the “index” (i.e., lblTest0, lblTest1, lblTest2, lblTest3) .
In the general declarations section of the form, I define a variable using the name of the control (without the index) As that type of control:
Public Class Form1
...
Private lblTest As Label
...
The Handles clause of the event procedure(s) for the control would include all four controls:
Private Sub lblTest_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles lblTest0.Click, lblTest1.Click, lblTest2.Click, lblTest3.Click
To simply know which one you are dealing with, you can use sender.Name:
Label1.Text = "You clicked on " & sender.Name
To get the “index” you can use code like this (in this case, the name “lblTest” has 7 characters, so I use 8 in my Mid function):
intIndex = CInt(Mid(sender.Name, 8))
Label2.Text = "The index is " & CStr(intIndex)
To really “use” the current control as its native type (in this case a Label), I do a “DirectCast” as follows:
lblTest = DirectCast(sender, Label)
So now you can use normal properties of the label, such as BackColor:
lblTest.BackColor = GetRandomColor()
(Note: "GetRandomColor" is a function in this particular example, defined as follows):
Public Function GetRandomColor() As Color
Dim objRandom As New Random
Return Color.FromArgb(255, _
objRandom.Next(0, 255), _
objRandom.Next(0, 255), _
objRandom.Next(0, 255))
End Function
To process the group of controls as an array, in a loop, I use the loop’s index to form the name of the current control, and I pass this name to a helper function I call “GetControlByName” within the DirectCast function. For example, below is a button which will toggle setting the text of all four labels to either blank or the word “TEST”. (The code for the helper function is shown after that.)
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
For i As Integer = 0 To 3
lblTest = DirectCast(GetControlByName(Me, "lblTest" & CStr(i)), Label)
lblTest.Text = IIf(lblTest.Text = "", "TEST", "")
Next
End Sub
The code for the helper function is:
Private Function GetControlByName(ByVal pobjParent As Control, _
ByVal pstrCtlName As String) _
As Control
Dim objCtl As Control
For Each objCtl In pobjParent.Controls
If objCtl.Name = pstrCtlName Then
Return (objCtl)
End If
Next
' if control is not found
Return Nothing
End Function
The sample application (screen-shot shown below) demonstrates the concepts discussed above. Download it here.