View Single Post
 
Old 07-26-2004, 05:26 PM
Iceplug's Avatar
Iceplug 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