65.9K
CodeProject is changing. Read more.
Home

VB.NET - A Different Approach to Creating Control Arrays - Create controls at Design Time, Process Them as a Control Array with Shared Event Handlers

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.20/5 (3 votes)

Sep 4, 2015

CPOL

2 min read

viewsIcon

15524

downloadIcon

166

VB.NET - A different approach to creating control arrays - Create controls at Design time, process them as a control array with shared event handlers

Introduction

This is a demonstration of a method to create an array of like-named controls that are created and placed on a form at design-time, not dynamically added at run-time.

I developed this when converting a VB6 app that used control arrays extensively to VB.NET, which as we all know, does not support control arrays in the same way VB6 did.

Normally, I would create the controls in Form_Load code, setting size and location, and adding to an array.

However, the project I was working on had several arrays of controls that were not evenly spaced on the form, so I could not use nice little loops incrementing x and y locations, etc. Additionally, I was having to make frequent changes regarding the number and placement of controls.

So I decided to go at it from a different direction. Now, I add all controls at design-time, placing and sizing them as needed. But, I name them all with a common base name plus a delimiter and a numeric extension.

Examples: btnGroupA_00, btnGroupA_01, btnGroupA_02

Then in Form_Load, I process them all into an array, assigning the numeric portion of the control name to the Tag property and assigning a shared Click Event.

Now, I have an array named btnGroupA() of buttons, all sharing one Click procedure.

This code uses generic Control object types because all I needed were Click events.

To try the attached code, start a new VB project and add some buttons to Form1 named btnTest_00, btnTest_01, btnTest_02, etc. and some CheckBoxes named chkTest_00, chkTest_01, ...

Background

A different approach to creating control arrays in VB.NET.

Using the Code

To try the attached code, start a new VB project and add some buttons to Form1 named btnTest_00, btnTest_01, btnTest_02, etc. and some CheckBoxes named chkTest_00, chkTest_01.

'-----------------------------------------------------------------------
' This is a demonstration of method to create an array of like-named
' controls that are created and placed on a form at design-time, not
' dynamically added at run-time.
'
' I developed this when converting a VB6 app that used control arrays
' extensively to VB.NET, which as we all know, does not support control
' arrays in the same way VB6 did.  
'
' Normally, I would create the controls in Form_Load code, setting
' size and location, and adding to an array.
'
' However, the project I was working on had several arrays of controls
' that were not evenly spaced on the form, so I could not use nice little
' loops incrementing x ynd y locations, etc.  Additionally, I was having
' to make frequent changes regarding the number and placement of controls.
'
' So I decided to go at it from a different direction.  Now, I add all
' controls at design-time, placing and sizing them as needed.  But, I
' name them all with a common base name plus a delimiter and a numeric
' extension. ex:  btnGroupA_00, btnGroupA_01, btnGroupA_02

' Then in Form_Load, I process them all into an array, assigning the
' numeric portion of the control name to the Tag property and assigning
' a shared Click Event.
'
' Now I have an array named btnGroupA() Of buttons, all sharing one
' Click procedure.
'
' This code uses generic Control object types because all I needed
' were Click events.
'
' To try this code, start a new VB project and add some buttons to Form1
' named btnTest_00, btnTest_01, btnTest_02 etc. and some checkBoxes named
' chkTest_00, chkTest_01 ...
'
' NOTE: this is for  demo purposes only.  No error checking, type checking, etc ....
'-----------------------------------------------------------------------
Public Class Form1

    '-- Arrays that will hold like-named form controls
    Dim myButtons(0) As Control
    Dim myCheckBoxes(0) As Control

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        '-- Declare Delegates for click event handling procedures
        Dim myButtonClickProc As New System.EventHandler(AddressOf myButtons_Click)
        Dim myCheckboxClickProc As New System.EventHandler(AddressOf myCheckbox_Click)

        '-- Look for controls named "btnTest_01", "btnTest_02" ....
        MakeControlArray(Me, "btnTest", myButtons, myButtonClickProc)

        '-- Look for controls named "chkTest_01", "chkTest_02" ....
        MakeControlArray(Me, "chkTest", myCheckBoxes, myCheckboxClickProc)

        '-- quick test of indexed access to the array of buttons
        myButtons(1).BackColor = Color.Red

    End Sub

    '------------------------------------------------------------------------------
    ' MakeControlArray
    ' Loop through the controls passed container, adding the one's that match the
    ' passed name pattern "ControlName_nnn" to a temporary dictionary.
    ' Then pull the controls out of the dictionary in sorted order and
    '  - put the control into the passed array
    '  - set the control Tag property to its Array index
    '  - set the controls Click event handler to the passed delegate procedure
    '------------------------------------------------------------------------------
    Private Sub MakeControlArray(ctlContainer As Control, _
                                 ctlName As String, _
                                 ByRef ctlArray() As Control, _
                                 clickDelegate As System.EventHandler)

        Dim ctrlDict As Dictionary(Of Integer, Object) = New Dictionary(Of Integer, Object)

        For Each ctl As Control In ctlContainer.Controls
            If ctl.Name.Contains("_") Then
                Try
                    Dim parts() As String = ctl.Name.Split("_")
                    If parts.Count = 2 Then
                        If parts(0) = ctlName Then
                            ctrlDict.Add(Val(parts(1)), ctl)
                        End If
                    End If
                Catch
                End Try
            End If
        Next

        If ctrlDict.Count > 0 Then
            '-- We have the controls in the ctrlDict, but don't know in what order
            '-- the numeric keys were added.
            '-- So, we sort the keys to a List, and loop through the List to add the controls
            '-- to the array in the proper based on the _nn naming convention
            ReDim ctlArray(ctrlDict.Count - 1)

            '-- Get the list of keys from the dictionary
            Dim keys As List(Of Integer) = ctrlDict.Keys.ToList

            '-- Sort the List of keys
            keys.Sort()

            '-- Loop through the keys, getting controls from the Dictionary and
            '-- putting them in the Array
            Dim pos As Integer = 0 '-- array position
            Dim x As Integer '-- Key balue

            For Each x In keys
                Dim b As New Control
                If (ctrlDict.TryGetValue(x, b)) Then
                    b.Tag = pos '-- set the control Tag with its array index
                    AddHandler b.Click, clickDelegate '-- Set the control's Click event handler
                    ctlArray(pos) = b
                    pos += 1
                End If
            Next
        End If
    End Sub

    '------------------------------------------------------------------
    ' Shared Click procedure for all Buttons in myButtons() array
    '------------------------------------------------------------------
    Public Sub myButtons_Click(sender As Object, e As EventArgs)

        MessageBox.Show("Button: " + sender.tag.ToString)

    End Sub

    '------------------------------------------------------------------
    ' Shared Click procedure for all CheckBoxes in myCheckBoxes() array
    '------------------------------------------------------------------
    Public Sub myCheckbox_Click(sender As Object, e As EventArgs)

        MessageBox.Show("Checkbox: " + sender.tag.ToString)

    End Sub

End Class

Points of Interest

A different approach to creating control arrays in VB.NET.

History

  • 4th September, 2015: Initial version