Control Arrays in .NET
Control Arrays in .NET
Control Arrays in .NET
Control Arrays in .NET
Control Arrays in .NET
Control Arrays in .NET Control Arrays in .NET Control Arrays in .NET Control Arrays in .NET Control Arrays in .NET Control Arrays in .NET Control Arrays in .NET Control Arrays in .NET
Control Arrays in .NET Control Arrays in .NET
Control Arrays in .NET
Go Back  Xtreme Visual Basic Talk > > > > Control Arrays in .NET


Reply
 
Thread Tools Display Modes
  #1  
Old 06-24-2004, 04:10 PM
Iceplug's Avatar
IceplugControl Arrays in .NET Iceplug is offline
MetaCenturion

Retired Moderator
* Guru *
 
Join Date: Aug 2001
Location: Iowa, USA
Posts: 16,583
Smile Control Arrays in .NET


After messing around in VB.NET, one might notice that there are no Index properties on the controls.
Incorrect Snap Conclusion one might make:
Oh... I can't make a control array!!! I can't make a list/grid of controls! No!!!

But... there are lots of ways to create a control array in .NET.

Under the hood of your form class
If you have ever spent some time looking in the Windows Forms Designer Code #region, you might notice the code required to actually set up a control on the form, in the case of a button, you will find the declaration, which is declared in the form's Declarations section:
Code:
    Friend WithEvents Button1 As System.Windows.Forms.Button
Next, instantiating the button:
Code:
        Me.Button1 = New System.Windows.Forms.Button
Then, there is the setting of the properties:
Code:
        Me.Button1.Location = New System.Drawing.Point(136, 96)
        Me.Button1.Name = "Button1"
        Me.Button1.Size = New System.Drawing.Size(88, 16)
        Me.Button1.TabIndex = 0
        Me.Button1.Text = "Button1"
Then, the button is added to the form.
Code:
        Me.Controls.Add(Me.Button1)
I can do that too!
OK, surely, we should be able to do something just like this for an array of controls. I mean, a For Loop or two should accomplish this same thing for an array. Let's try it.

Declaration in the form:
Code:
    Friend WithEvents Buttons(99) As Button
Drat... an error! WithEvents cannot be typed as arrays... so, we can't use WithEvents on an array declaration.
Ah... frustrated, let's get rid of it.
Code:
    Friend Buttons(99) As Button
Another incorrect snap conclusion: So much for actually having an event handlers for this array.
We'll discuss adding events later. Back to our Button Friends.

There is the instantion, the setting of the properties, and the form getting the button added onto it; let's do all of those in the For loop:
Code:
    Dim LV As Integer
        For LV = 0 To 99 

            Buttons(LV) = New Button  'Create the button.
'It has a default width and height.
            Buttons(LV).Left = Buttons(LV).Width * (LV Mod 10)
            Buttons(LV).Top = Buttons(LV).Height * (LV \ 10)
            Buttons(LV).Name = "Btn" & LV
            Buttons(LV).Text = LV.ToString()

            Me.Controls.Add(Buttons(LV))

        Next
Ahh... that looks decent.
And... it works! Yay!
Control arrays! *Dance*
OK, now, why can't I get any events to my array?

Yes, you can get events for the buttons in the array.
Code:
    Public Sub ButtonClickEventProc(ByVal sender As Object, ByVal e As EventArgs)
    'I want this event to run for all of the controls.
    End Sub
Now, using Handles at the end of this subroutine doesn't work...
You'd only get controls declared WithEvents, and since we can't use WithEvents on the control array... how can we possibly add an event to the control?

... AddHandler.

Taking a look at event handling at runtime should popup two keywords: AddHandler and RemoveHandler... since we don't need to remove any events, AddHandler looks promising.

Let's AddHandler
So, in our For Loop, we can Add Handlers to the buttons in the array.
Code:
            AddHandler Buttons(LV).Click, AddressOf ButtonClickEventProc
And now, we have an event set up for the control array!

Addenda:
  • You can add a one-dimensional array of controls to the form by using Me.Controls.AddRange
  • You can modify the button that you clicked on by DirectCasting the sender into a button: Dim btn As Button = DirectCast(sender, Button)
  • You can have a multi-dimensional array of controls as well.
  • You can add a control to the control array by Declaring another button instance and doing the above to create a new control.
  • You can handle any event.
  • Your event handler procedure must have the right signature... which means the sub must have (sender As Object, e As ???), where ??? is some brand of event args (for a click, it is just EventArgs, and for a mouse event, it is MouseEventArgs)

So, here is a form with a button control array. (As a .vb file)
Code:
Imports System
Imports System.Windows.Forms

Public Class Controlland
    Inherits System.Windows.Forms.Form

    Friend Buttons(99) As Button
    'Declare the buttons.

    Public Sub New() 'This is the Sub New, the constructor, etc.

        MyBase.New()  'Initialize the form itself.

        CreateArray()

    End Sub

    Public Sub CreateArray() 'This subroutine initializes the array.

        'This will be done in a For Loop
        Dim LV As Integer  'LV is our loop variable.

        For LV = 0 To 99 'Set up the loop to go through each button in the array.

            Buttons(LV) = New Button  'Create the button.
            'This creates the button at the top left of the form with the default size.

            Buttons(LV).Left = Buttons(LV).Width * (LV Mod 10)
            Buttons(LV).Top = Buttons(LV).Height * (LV \ 10)
            'Initializes the button locations.

            Buttons(LV).Name = "Btn" & LV
            Buttons(LV).Text = LV.ToString()

            'Add an event handler and whatever you may want to add.
            AddHandler Buttons(LV).Click, AddressOf ButtonClickEventProc
            'This event handler handles the click event of all of the buttons.

        Next

        Me.Controls.AddRange(Buttons)
        'Add... ALLLL of the buttons to the form.

    End Sub


    Public Sub ButtonClickEventProc(ByVal sender As Object, ByVal e As EventArgs)
        'Button control array event handler.
        'sender has to be recast as a Button
        Dim Btn As Button = DirectCast(sender, Button)
        Btn.Enabled = False

    End Sub

    Public Shared Sub Main()
        Dim F As Controlland = New Controlland
        F.ShowDialog()
    End Sub


End Class
__________________

Iceplug, USN
Quadrill 1 Quadrill 2 (full) Quadrill 3 JumpCross .NET Website is ALIVE! - DL Platform Tour for VB.NET! Posting Guidelines Hint: Specify your location in your user cp profile if you want compassion!

Last edited by Colin Legg; 07-31-2010 at 01:43 PM. Reason: tidied up code tags
Reply With Quote
  #2  
Old 07-26-2004, 05:26 PM
Iceplug's Avatar
IceplugControl Arrays in .NET Iceplug is offline
MetaCenturion

Retired Moderator
* Guru *
 
Join Date: Aug 2001
Location: Iowa, USA
Posts: 16,583
Default

Two of my readers have posed interesting questions about increasing the functionality of the control array that we have created here, and I will demonstrate them here as well.

How to add buttons to the control array at runtime?
The solution requires us to modify our original idea of using a fixed array for the control array. The idea is that our control array will have a dynamic size and grow larger during runtime.

We *could* do this with a dynamic array in .NET, but dynamic array resizing is a very VB specific feature, not a .NET feature.
While one can do:
Code:
Dim X() As Integer
'and then
X = New Integer (10) {}    
'or
X = New Integer () {10, 20, 30, 40, 50, 60, 70, 80, 90, 100}
Both of those methods are fine. The non-NET culprit is the Redim statement, which is not .NET.

For our control array, we cannot use the first option
Buttons = New Button (10) {}
This is equivalent to Redim without Preserve. We get a new empty array.
Buttons = New Button () {A, B, C, D, E, F, G, H, I, J}
And that would be ridiculous (it also requires that we know the size of the array at design-time.

Our solution: ArrayList.
If you have never used the ArrayList, you should try it. It's a wonderful way to store unknown numbers of items... and it's very similar to a VB6 Collection, if you are familiar with VB6, except with more power.

So, we redesign our control array for use with an ArrayList.
First, we declare our Arraylist.
Code:
    Public Sub CreateArray() 'This subroutine initializes the array.
        Friend Buttons As ArrayList
Now, there is the traditional setting-of-properties subroutine that we must redesign .
Code:
        Buttons = New ArrayList(67)  'Creates the arraylist.  The number 67 isn't very important.
        'But you should keep it as close to the maximum as possible.
This instantiates the arraylist. The number that you supply as the capacity isn't important (the capacity will increase itself if you go over), but you should generally try to keep the capacity as close to the maximum value without going over. If you don't know if your array is going to have a maximum, then just pick a number and move on.

Of course we have to initialize the buttons.
We can do this in a For Loop again.
It's very similar to how we did it in part one.
Our Btn As Button is a representative for each button that we add to the control array.

Code:
        Dim LV As Integer
        Dim Btn As Button
        For LV = 0 To 49
            'The property setting ceremony.
            Btn = New Button
            Btn.Left = Btn.Width * (LV Mod 10)
            Btn.Top = Btn.Height * (LV \ 10)
            Btn.Text = "???"
            AddHandler Btn.Click, New EventHandler(AddressOf WhenClicked)

            Me.Controls.Add(Btn)
            Buttons.Add(Btn)
        Next

    End Sub
Notice that we are adding the Btn to the form's controls AND the Buttons arraylist.

Our event procedure:
Code:
    Private Sub WhenClicked(ByVal sender As Object, ByVal e As EventArgs)
        Dim Btn As Button = DirectCast(sender, Button)

        Dim RelIndex As Integer = Buttons.IndexOf(sender)
        Btn.Text = RelIndex.ToString()

        'That is a handy way of determining the 'Index' of your control array item if you so desire.
        'The LBound is always zero due to the Arraylist and .NET in General.
        'The UBound is found as Buttons.Count - 1

    End Sub
The Index of the Button Clicked
In case you were wondering how to get the index of the control that you clicked:
Dim RelIndex As Integer = Array.IndexOf(Buttons, sender)
And RelIndex contains the index of the item that the user clicks.


Now that all of this has been setup:
How to add buttons to the control array at runtime?

The answer lies here: We have created the arraylist and now, since you know the arraylist has a dynamic size, adding buttons to the form should be a piece of cake... and it is.

Add this to the CreateArray subroutine.
Code:
        'Click the form to add a new button to the array.
        AddHandler Me.Click, New EventHandler(AddressOf FormClicked)
And now to add a button when you click the form:
Code:
    Private Sub FormClicked(ByVal sender As Object, ByVal e As EventArgs)
        Dim Btn As Button = New Button
        'Our new button enlistee :}.
        Dim Endex As Integer = Buttons.Count

        'Set the properties.
        Btn.Left = Btn.Width * (Endex Mod 10)
        Btn.Top = Btn.Height * (Endex \ 10)
        Btn.Text = "???"
        AddHandler Btn.Click, New EventHandler(AddressOf WhenClicked)

        Me.Controls.Add(Btn)
        Buttons.Add(Btn)
    End Sub
Really, a new Button is just instantied and its properties are set. What makes it become a member of the control array is the fact that it is added to the Me.Controls collection and the Buttons arraylist.
Me.Controls.Add(Btn)
Buttons.Add(Btn)

The controls index is simply Buttons.Count, assigned to Endex (the End index).
The index for our new button is not entirely important: you can just add the button directly to Me.controls and Buttons without using the Endex.
It's a handy way to get the index if you want it. (Like if you want the buttons to line up).

But, I hope you learned something interesting from this demonstration.

Addenda:
  • Once again you can have any type of control instead of Button for the control array.
  • You cannot have a multi-dimensional arraylist, unless you store arrays in the arraylist.
  • You can handle any event.
  • The fourth addendum in the previous post is a misnomer... the control created is not in the array.
So, here's our dynamic control array.
Code:
Imports System
Imports System.Collections
Imports System.Windows.Forms

Public Class Controlland
    Inherits System.Windows.Forms.Form

    Dim Buttons As ArrayList
    'Declare the buttons.

    Public Sub New() 'This is the Sub New, the constructor, etc.

        MyBase.New()  'Initialize the form itself.

        CreateArray()

    End Sub

    Public Sub CreateArray() 'This subroutine initializes the array.
        Dim LV As Integer
        Dim Btn As Button
        Buttons = New ArrayList(67)  'Creates the arraylist.  The number 67 isn't very important.
        'But you should keep it as close to the maximum as possible.

        For LV = 0 To 49
            'The property setting ceremony.
            Btn = New Button
            Btn.Left = Btn.Width * (LV Mod 10)
            Btn.Top = Btn.Height * (LV \ 10)
            Btn.Text = "???"
            AddHandler Btn.Click, New EventHandler(AddressOf WhenClicked)

            Buttons.Add(Btn)
            Me.Controls.Add(Btn)
        Next

        'Click the form to add a new button to the array.
        AddHandler Me.Click, New EventHandler(AddressOf FormClicked)

    End Sub


    Private Sub WhenClicked(ByVal sender As Object, ByVal e As EventArgs)
        Dim Btn As Button = DirectCast(sender, Button)

        Dim RelIndex As Integer = Buttons.IndexOf(sender)
        Btn.Text = RelIndex.ToString()

        'That is a handy way of determining the 'Index' of your control array item if you so desire.
        'The LBound is always zero due to the Arraylist and .NET in General.
        'The UBound is found as Buttons.Count - 1

    End Sub

    Private Sub FormClicked(ByVal sender As Object, ByVal e As EventArgs)
        Dim Btn As Button = New Button
        'Our new button enlistee :}.
        Dim Endex As Integer = Buttons.Count

        'Set the properties.
        Btn.Left = Btn.Width * (Endex Mod 10)
        Btn.Top = Btn.Height * (Endex \ 10)
        Btn.Text = "???"
        AddHandler Btn.Click, New EventHandler(AddressOf WhenClicked)

        Me.Controls.Add(Btn)
        Buttons.Add(Btn)
    End Sub

    Public Shared Sub Main()
        Dim F As Controlland = New Controlland
        F.ShowDialog()
    End Sub


End Class
*Color syntaxed for your enjoyment.
__________________

Iceplug, USN
Quadrill 1 Quadrill 2 (full) Quadrill 3 JumpCross .NET Website is ALIVE! - DL Platform Tour for VB.NET! Posting Guidelines Hint: Specify your location in your user cp profile if you want compassion!

Last edited by Colin Legg; 07-31-2010 at 01:39 PM. Reason: tidied up code tags
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
Control Arrays in .NET
Control Arrays in .NET
Control Arrays in .NET Control Arrays in .NET
Control Arrays in .NET
Control Arrays in .NET
Control Arrays in .NET Control Arrays in .NET Control Arrays in .NET Control Arrays in .NET Control Arrays in .NET Control Arrays in .NET Control Arrays in .NET
Control Arrays in .NET
Control Arrays in .NET
 
Control Arrays in .NET
Control Arrays in .NET
 
-->