0

I need to loop through all Checkboxes on a form and get the Tag property for each. The Checkboxes are in Groupboxes, and nested Groupboxes. Code I have works for the main form, it is not getting the values from the Checkboxes in the Groupboxes

...

            i = 0

            For Each ctrl As Control In Me.Controls

                If (TypeOf ctrl Is CheckBox) Then

                    'Resize array
                    ReDim Preserve g_str_Array(i)

                    'Add Tag to array
                    g_str_Array(i) = CStr(ctrl.Tag)

                    i += 1

                End If

            Next

...

Terabithia
  • 105
  • 2
  • 10

1 Answers1

1

Here's a method that you can add to a form that provides access to every control on the form via the Tab order:

Public Iterator Function GetControls() As IEnumerable(Of Control)
    Dim ctrl = GetNextControl(Me, True)

    Do Until ctrl Is Nothing
        Yield ctrl

        ctrl = GetNextControl(ctrl, True)
    Loop
End Function

Because that is an iterator, you can chain other LINQ methods to it. To get the Tag of each CheckBox into an array:

Dim checkBoxTags = GetControls().OfType(Of CheckBox)().
                                 Select(Function(cb) CStr(cb.Tag)).
                                 ToArray()

If you wanted to use this method for multiple forms then, rather than repeating the code in each of them, you can add a single extension method:

Imports System.Runtime.CompilerServices

Public Module FormExtensions

    <Extension>
    Public Iterator Function GetControls(source As Form) As IEnumerable(Of Control)
        Dim ctrl = source.GetNextControl(source, True)

        Do Until ctrl Is Nothing
            Yield ctrl

            ctrl = source.GetNextControl(ctrl, True)
        Loop
    End Function

End Module

and then call it in each form as though it were a member.

jmcilhinney
  • 50,448
  • 5
  • 26
  • 46
  • Thanks jmcilhinney, this looks like it will almost work. It does return the desired values, however they are not in order. Array element 0 should be set the the Tag property for Checkbox00, element 1 to Checkbox 01, etc. The tabindexes are in order, any suggestions? The numeric portion of the Checkbox names does indicate the array element position. – Terabithia Nov 20 '20 at 00:53
  • @Terabithia, the `GetNextControl` works on the Tab order. Have you set a sensible Tab order to the controls on your form? It's not guaranteed but I would generally expect the Tab order and the numerical order of those controls to match. Regardless, if they are named consistently and numerically then you can just order them by name before getting the `Tag` values. In the second code snippet, throw `.OrderBy(Function(cb) cb.Name)` in between the `OfType` and `Select` calls. – jmcilhinney Nov 20 '20 at 01:43
  • that suggestion worked, Thank You, though i will need to make a change to the Checkbox naming. As there are over 100 controls involved, I need to add leading zero's to the numeric portion of the name to make it sort correctly, which is doable enough. (CheckBox1 becomes CheckBox001) – Terabithia Nov 20 '20 at 04:47
  • @Terabithia, you could include code in the `OrderBy` method to get the digit(s) off the end of the name and convert that to an actual number, but adding the zeroes keeps the code simpler. – jmcilhinney Nov 20 '20 at 04:51