1. Technology
Send to a Friend via Email

VB.NET: What Happened to Control Arrays!!! (Part I)

VB.NET no longer supports VB 6 Control Arrays
Here's what you can do about it. Part II is another point of view.

MicroSoft's Recommended Solution

Frank Bugeja, About Visual Basic reader from Australia ...

<G'day Mate!>

... writes,

I am a senior computing studies teacher teaching software design and development. I have been using Visual Basic 6.

Despite the fact that online experts of VB.NET and authors of VB.NET textbooks are saying that the omission of control arrays in VB.NET is a positive step, the omission of control arrays from VB.NET is, for educational purposes in teaching about arrays, a decidedly backward step.

Why?

  1. No longer is it possible to simply copy a control, such as a textbox, and then paste it (once or several times) to create a control array.
  2. The VB.NET code for creating a structure similar to a control array has been, in all the books on VB.NET that I have bought and online, much longer and much more complex. It lacks the simplicity of coding a control array that is found in VB6.

For example, to clear a control array of 6 labels of text in VB6, it is as simple as this:

  For a = 1 to 6
  	Label(a).Caption = ""
  Next

Could you please show me how I can create a "control array" structure in VB.NET, and how it would be coded (using labels as the controls).


Well, mate ... Pull your swag up closer to the bush telly and we'll have a go at it!

In the style of a Clint Eastwood spaghetti western, I'm going to give you the Good, the Bad, and the really, really UGLY about this. And I do mean Ugly. We're talking "kiss your maiden aunt through an inch of pancake makeup" ugly here. In reverse order ...

The Ugly

You're absolutely right!

Well ... You're mainly right. If you reference the VB6 compatibility library, there are objects in there that act pretty much like control arrays. To see what I mean, simply use the VB.NET upgrade wizard with a program that contains a control array. The code is back to uh-uh-ugly again, but it works. The bad news is that Microsoft will not guarantee that the compatibility components will continue to be supported and you're not supposed to use them.

The VB.NET code to create and use "control arrays" is much longer and much more complex. But you don't have to buy a book to see that. You just have to check out Microsoft's white paper about it: Creating Control Arrays in Visual Basic .NET. Microsoft heard this complaint quite a bit so they wrote this official response. The code in the white paper is for both C# and VB.NET and also uses buttons rather than labels as you requested. So here's my (hopefully) simplified version of the white paper using labels.

According to Microsoft, to do something even close to what you can do in VB 6 requires the creation a "simple component that duplicates control array functionality". I'll let you be the judge ... but it doesn't look like a duplicate to me. And it's nothing close to being as simple.

First the code.

You need both a new class and a hosting form to illustrate this. The end result can be seen at the top of this article. The class actually creates and destroys new labels. The complete class code is as follows:
Public Class LabelArray
    Inherits System.Collections.CollectionBase
    Private ReadOnly HostForm As _
	System.Windows.Forms.Form
    Public Function AddNewLabel() _
	As System.Windows.Forms.Label
        ' Create a new instance of the Label class.
        Dim aLabel As New System.Windows.Forms.Label
        ' Add the Label to the collection's
	' internal list.
        Me.List.Add(aLabel)
        ' Add the Label to the Controls collection   
        ' of the Form referenced by the HostForm field.
        HostForm.Controls.Add(aLabel)
        ' Set intial properties for the Label object.
        aLabel.Top = Count * 25
        aLabel.Width = 50
        aLabel.Left = 140
        aLabel.Tag = Me.Count
        aLabel.Text = "Label " & Me.Count.ToString
        Return aLabel
    End Function
    Public Sub New( _
	ByVal host As System.Windows.Forms.Form)
        HostForm = host
        Me.AddNewLabel()
    End Sub
    Default Public ReadOnly Property _
        Item(ByVal Index As Integer) As _
        System.Windows.Forms.Label
        Get
            Return CType(Me.List.Item(Index), _
		System.Windows.Forms.Label)
        End Get
    End Property
    Public Sub Remove()
        ' Check to be sure there is a Label to remove.
        If Me.Count > 0 Then
            ' Remove the last Label added to the array 
            ' from the host form controls collection. 
	    ' Note the use of the default property in 
            ' accessing the array.
            HostForm.Controls.Remove(Me(Me.Count - 1))
            Me.List.RemoveAt(Me.Count - 1)
        End If
    End Sub
End Class

To illustrate how this class code would be used, you could create a Form that calls it. You would have to use the code shown below in the form:

Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

' Also you must add the statement:
'   MyControlArray = New LabelArray(Me)
' after the InitializeComponent() call in the 
' hidden Region code.

    ' Declare a new ButtonArray object.
    Dim MyControlArray As LabelArray

    Private Sub btnLabelAdd_Click( _
	ByVal sender As System.Object, _
	ByVal e As System.EventArgs) _
	Handles btnLabelAdd.Click
        ' Call the AddNewLabel method 
        ' of MyControlArray.
        MyControlArray.AddNewLabel()
        ' Change the BackColor property 
        ' of the Button 0. 
        MyControlArray(0).BackColor = _
		System.Drawing.Color.Red
    End Sub

    Private Sub btnLabelRemove_Click( _
	ByVal sender As System.Object, _
	ByVal e As System.EventArgs) _
	Handles btnLabelRemove.Click
        ' Call the Remove method of MyControlArray.
        MyControlArray.Remove()
    End Sub
End Class

First, this doesn't even do the job at Design Time like we used to do it in VB 6! And second, they aren't in an array, they are in a VB.NET Collection - a much different thing than an array.

The Bad

Microsoft has the nerve lie to all of us by calling this a "duplicate"!

The Good

Somehow ... I think that the marketing people at Microsoft are really to blame for problems like this. They are the ones who try to keep the fiction alive that VB.NET and VB 6 are anything more than distantly related. If you just accept the fact that VB.NET is a whole new language ... with great new features! ... then you can understand things a lot better. Regular readers of this site know that I'm a real advocate of VB.NET. I think it's a great language and is destined to dominate the development landscape more than VB 6 ever did.

The reason VB.NET doesn't support the VB 6 "Control Array" is that there is no such thing as a "Control" "Array" (note the change of quotation marks). VB 6 creates a collection "behind the scenes" and makes it appear as an array to the developer. But it's not an array and you have little control over it beyond the functions provided through the IDE.

VB.NET, on the other hand, calls it what it is: a collection of objects. And they hand the keys to the kingdom to the developer by creating the whole thing right out in the open.

Mixed Controls Example

As an example of the kind of advantages this gives the developer, in VB 6 the controls had to be of the same type, and they had to have the same name. Since these are just objects in VB.NET, you can make them different types and give them different names and still manage them in the same collection of objects.

In this example, the same Click event handles two buttons and a checkbox and displays which one was clicked. Do that in one line of code with VB 6!

Private Sub MixedControls_Click( _
    ByVal sender As System.Object, _
    ByVal e As System.EventArgs) _
    Handles Button1.Click, _
            Button2.Click, _
            CheckBox1.Click
    ' The statement below has to be one long statement!
    ' It's on four lines here to keep it narrow
    ' enough to fit on a web page
    Label2.Text = 
    Microsoft.VisualBasic.Right(sender.GetType.ToString, 
    Len(sender.GetType.ToString) - 
    (InStr(sender.GetType.ToString, "Forms") + 5))
End Sub

The substring calculation is kind of complex, but it isn't really what we're talking about here. You could do anything in the Click event. You could, for example, use the Type of the control in an If statement to do different things for different controls.

And the Better Than Good!!

Indications are that the Whidbey upgrade to VB.NET will have CONTROL ARRAYS back again. Since it hasn't been released yet, nobody but Bill knows for certain ... but it's a fairly good bet right now.

But that's not all!!!

After this article was completed and published, Frank forwarded a different point of view about VB.NET and control arrays to me. It's interesting ... but I don't completely agree. You can read all about it in what is now Part II of this article.

And a few weeks further on, About Visual Basic reader John Fannon contributed one more solution for VB.NET "control arrays" - this time using subroutine approach that is a bit easier to code than Microsoft's "official" position. You can read about John's suggestion in Part III of this article.

©2014 About.com. All rights reserved.