1. Home
  2. Computing & Technology
  3. Visual Basic
VB.NET: What Happened to Control Arrays!!! (Part III)
Control Arrays in VB.NET don't have to be that hard!
But there are some interesting gotcha's involved!
John's solution

About Visual Basic Reader John Fannon decided to take up the challenge of Control Arrays in VB.NET and came up with what he says is an easier approach. Let's see what he did.

If you happened to find this article by searching and you haven't read the first parts yet, here's the link for Part I of this article and Part II of this article.

Revision! John kept working his solution and now has new conclusions! That doesn't invalidate what he discovered and reported in this article however. His new ideas have been added at the end of this article.


John wrote:

I needed control arrays because I wanted to put a simple table of numbers on a form at run time. I didn't want the nausea of placing them all individually and I wanted to use VB.NET.

As pointed out on About Visual Basic, Microsoft offers a very detailed solution to a simple problem, but it's a very large sledgehammer to crack a very small nut. (See Part I of this article.) After some experimentation, I eventually hit upon a solution. Here's how I did it.

The About Visual Basic example from Part I shows how you can create a TextBox on a Form by creating an instance of the object, setting properties, and adding it to the Controls collection that is part of the Form object.

Dim txtDataShow As New TextBox
txtDataShow.Height = 19
txtDataShow.Width = 80
txtDataShow.Location = New Point(X, Y)
Me.Controls.Add(txtDataShow)

Although the Microsoft solution creates a Class, I reasoned that it would be possible to wrap all this in a subroutine instead. Every time you call this subroutine you create a new instance of the textbox on the form. Here's the complete code:

Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

    Private Sub BtnStart_Click( _
        ByVal sender As System.Object, _
        ByVal e As System.EventArgs) _
        Handles btnStart.Click

        Dim I As Integer
        Dim sData As String
        For I = 1 To 5
            sData = CStr(I)
            Call AddDataShow(sData, I)
        Next
    End Sub
    Sub AddDataShow( _
        ByVal sText As String, _
        ByVal I As Integer)

        Dim txtDataShow As New TextBox
        Dim UserLft, UserTop As Integer
        Dim X, Y As Integer
        UserLft = 20
        UserTop = 20
        txtDataShow.Height = 19
        txtDataShow.Width = 25
        txtDataShow.TextAlign = _
            HorizontalAlignment.Center
        txtDataShow.BorderStyle = _
            BorderStyle.FixedSingle
        txtDataShow.Text = sText
        X = UserLft
        Y = UserTop + (I - 1) * txtDataShow.Height
        txtDataShow.Location = New Point(X, Y)
        Me.Controls.Add(txtDataShow)
    End Sub
End Class

Very good point, John. This is certainly a lot more simple than the Microsoft code ... so I wonder why they insisted on doing it that way?

To begin our investigation, let's try changing one of the property assignments in the code. Let's change

txtDataShow.Height = 19

to

txtDataShow.Height = 100

just to make sure that there is a noticeable difference.

When we run the code again, we get ... Whaaaat??? ... the same thing. No change at all. In fact, you can display the value with a statement like MsgBox (txtDataShow.Height) and you still get 20 as the value of the property no matter what you assign to it. Why does that happen?

The answer is that we're not deriving our own Class to create the objects, we're just adding things to another Class so we have to follow the rules of the other class. And those rules state that you can't change the Height property. (Wellllll ... you can. If you change the Multiline property to True, then you can change the Height.)

Why VB.NET goes ahead and executes the code without even a whimper that there might be something wrong when, in fact, it totally disregards your statement is a whole 'nother gripe. I might suggest at least a warning in the compile, however. (Hint! Hint! Hint! Is Microsoft listening?)

The example from Part I inherits from another Class, and this makes the properties available to the code in the inheriting Class. Changing the Height property to 100 in this example gives us the expected results. (Again ... one disclaimer: When a new instance of a large Label component is created, it covers up the old one. To actually see the new Label components, you have to add the method call aLabel.BringToFront().)

This simple example shows that, although we CAN simply add objects to another Class (and sometimes this is the right thing to do), programming control over the objects requires that we derive them in a Class and the most organized way (dare I say, "the .NET way" ??) is to create properties and methods in the new derived Class to change things. John remained unconvinced at first. He said that his new approach suits his purpose even though there are limitations from not being "COO" (Correctly Object Oriented). More recently, however, John wrote,

" ... after writing a set of 5 textboxes at runtime, I wanted to update the data in a subsequent part of the program - but nothing changed - the original data was still there.

(DJM Note: RIGHT! That's because these inherited properties can't be changed at runtime!)

I found that I could get round the problem by writing code to take off the old boxes and putting them back again with new data. A better way to do it would be to use Me.Refresh. But this problem has drawn my attention for the need to supply a method to subtract the textboxes as well as add them."

John then enclosed code which used a global variable to keep track of how many controls had been added to the form so a method ...

Private Sub Form1_Load( _
   ByVal sender As System.Object, _
   ByVal e As System.EventArgs) _
   Handles MyBase.Load
   CntlCnt0 = Me.Controls.Count
End Sub

Then the "last" control could be removed ...

N = Me.Controls.Count - 1
Me.Controls.RemoveAt(N)

John noted that, "maybe this is a bit clumsy."

Oh! I dunno about that, John. It's the way Microsoft keeps track of objects in COM AND in their "ugly" example code in Part I. I think it's a wonderful example that actually puts the last ten years of OOP thinking at Microsoft in a capsule view. In any case, John's latest conclusion is ...

I've now returned to the problem of dynamically creating controls on a form at run time and I have been looking again at the 'What Happened to Control Arrays' articles.

I have created the classes and can now place the controls onto the form in the way I want them to be.

John even enclosed code which demonstrated how to control the placement of controls in a group box using the new classes he has started using. Maybe Microsoft had it right in their "ugly" solution after all!

This series is growing because a lot of you are writing in about it! I'd love hear your point of view.

Explore Visual Basic
By Category
About.com Special Features

Holiday Central

What to eat, where to go, fun things to do and how to save money on the perfect gifts. More >

Family Tech Center

Stay connected and entertained with reviews on tips on the latest HDTVs, cellphones and more. More >

  1. Home
  2. Computing & Technology
  3. Visual Basic

©2009 About.com, a part of The New York Times Company.

All rights reserved.