1

Coming from VB6 where you could have control arrays. When you named a control the same as another you could create a control array and then refer to each instance of the control by index.

I was wondering how we do this in VB.NET. Currently I have to do this which is tedious:

lblDetails1.Text = ""
lblDetails2.Text = ""
lblDetails3.Text = ""
lblDetails4.Text = ""
lblDetails5.Text = ""
lblDetails6.Text = ""
lblDetails7.Text = ""
lblDetails8.Text = ""
lblDetails9.Text = ""
lblDetails10.Text = ""
lblDetails11.Text = ""
.
.
.
lblDetails40.Text = ""

Regards

Graham

Thraka
  • 2,065
  • 19
  • 24
Graham Jones
  • 165
  • 4
  • 19
  • You can store the names in a `List(of String)` and use that to loop thru Me.Controls or store a reference to the actual control in a `List(of Label)` – Ňɏssa Pøngjǣrdenlarp Sep 10 '15 at 14:49
  • 1
    Here's a link to question I think is similar to what you are asking. I used Linq in my answer. Also the original poster has another way of doing what you want. http://stackoverflow.com/questions/29832504/changing-the-text-of-all-the-buttons-on-a-form-in-vb-net/29832737#29832737 – Timmy Sep 10 '15 at 14:55
  • Look for some sample code to loop through all controls and test for `TextBox`. Note that a control and be a container with other controls. The top level Me.Controls on returns the top level. – rheitzman Sep 10 '15 at 14:55
  • "Coming from VB6 where you could have control arrays" and what makes you think that VB.NET cannot? VB.NET is a notably improved version of VB6 and, as such, can do anything (good) that VB6 can and usually better (you have even the option of relying on quite a few VB6 functionalities if you prefer). You can have collections of any kind (not just arrays, but lists, dictionaries, etc.) of controls, of specific types of controls (e.g., labels), of classes defined on account of many properties, controls among them, etc. – varocarbas Sep 10 '15 at 14:55
  • 1
    @varocarbas vb6 ide did create the array by itself. In vs we have to create the array on our own. – the_lotus Sep 10 '15 at 15:01
  • @the_lotus I don't think that writing `Dim allControls(40) As Control allControls(0) = lblDetails1 allControls(1) = lblDetails2 ` etc. Is a big deal. In any case the statement "VB.NET does not have arrays of controls" sounds very misleading. – varocarbas Sep 10 '15 at 15:03
  • 1
    The simple way to have a "control array" in VB6 is NOT supported in VB.NET (and also not in C#). The old VB6 heads used to have an (example: Label) "control array" named "lblWhatever ...", and accessed it like any array.Iterating through the forms controls collection is not the same. If you have different "control arrays" of the same type on your form, you have to check the name (or the tag value or do some other magic). All not necessary with VB6 .... Not everthing grew better with .NET – Thomas Krojer Sep 10 '15 at 15:08
  • @the_lotus Additionally what is then the [container].Controls collection? It is precisely an array-like (= equivalent to VB6 array) variable storing all the controls contained by the given parent (e.g., the main form, for example). – varocarbas Sep 10 '15 at 15:10
  • 1
    It is hard to answer your question without context - why you need this? `dim controlNames as List(of string)`... `Myform.Controls.find(controlNames(0), true)`. Controls are stored inside other controls already. So you have pretty good control hierarchy. And if you have some very dynamic code, your code can be based on `controls.find`. – T.S. Sep 10 '15 at 15:12
  • 1
    `yourFromName.Controls.OfType().ToList().ForEach(textBox => textBox.Clear());` – MethodMan Sep 10 '15 at 19:21
  • I fell like I have started quite a debate. let me elaborate further. in my programme I have a lot of 'code' lblStudentname1.text = sname(1) 'code' in vb6 I could of done a 'FOR' loop with 'code' lblStudentName(n).text = sname(n) 'code' – Graham Jones Sep 10 '15 at 19:36
  • 1
    Few mourn the loss of Control Arrays because there are faster, better ways, many of them sprinkled throughout. The VB version of @MethodMan 's code using a label would be: `Me.Controls.OfType(Of Label).ToList().ForEach(Function(q) q.Text = "")`. It one line of code: try it! As for populating them, an OOP app would have a `Student` class which does that, so there would only be one such block anywhere ever e.g. `Student.UpdateDisplay()` – Ňɏssa Pøngjǣrdenlarp Sep 10 '15 at 22:15
  • possible duplicate of [Control Array in vb.net](http://stackoverflow.com/questions/5497403/control-array-in-vb-net) and [control array vb.net](http://stackoverflow.com/questions/14789112/control-array-vb-net) and [Visual Basic 2010 Creating a Control Array](http://stackoverflow.com/questions/3795253/visual-basic-2010-creating-a-control-array) and [How to create Control Arrays in VB .NET](http://stackoverflow.com/questions/5299435/how-to-create-control-arrays-in-vb-net) – C-Pound Guru Sep 11 '15 at 13:59

3 Answers3

1

This is pretty simple, you could loop through the controls.

for (int i = 0; i < this.Controls.Count - 1; i++)
{
    if (this.Controls[i].GetType() == typeof(TextBox))
    {
        ((TextBox)this.Controls[i]).Clear();
    }
}
jac
  • 9,666
  • 2
  • 34
  • 63
  • 2
    This only if controls have one surface. What if they are nested in 30 layers? Recursion is needed. – T.S. Sep 10 '15 at 15:25
  • @T.S., True, this is the simplest example possible, based only on what is currently in the OP's question. – jac Sep 10 '15 at 15:27
  • 1
    We really don't know what OP is asking. Totally out of context – T.S. Sep 10 '15 at 15:31
  • Yes we do know what he's asking.. control arrays were a VB6 concept implemented through the form designer. A simple search will tell you how it works... – Thraka Sep 10 '15 at 18:42
1

Control arrays were a VB6 designer type concept that didn't port over into .NET WinForms. However, you can mimic the behavior by searching through all controls and checking if the name starts with the same text, and then adding those that match into an array.

I've created an extension method for you. Just save this as a new module in your project and on any form you can call it.

Imports System.Runtime.CompilerServices

Public Module FormExtensions
    <Extension()>
    Public Function GetControlArray(Of TControl As Control)(extForm As Form, namePart As String, container As Control) As IEnumerable(Of TControl)


        Dim controls = From control In container.Controls.OfType(Of TControl)
                       Where control.Name.StartsWith(namePart)
                       Select control

        Dim containerSets = From control In container.Controls.OfType(Of Control)
                            Where control.Controls.Count > 0
                            Select GetControlArray(Of TControl)(extForm, namePart, control)

        For Each item As IEnumerable(Of TControl) In containerSets
            controls = controls.Union(item)
        Next

        Return controls
    End Function
End Module

Now in your form, you can call it and loop through the controls. In this example I get all of the labels that start with a specific name and then change the text to match. The order of the controls is based on the order they were added to the form.

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    Dim controls = GetControlArray(Of Label)("MyLabel", Me)

    For Each item As Label In controls
        item.Text = "Found"
    Next

End Sub

The labels I had added to the form were named like this (taken from the designer generated code)

Me.MyLabel1 = New System.Windows.Forms.Label()
Me.MyLabel2 = New System.Windows.Forms.Label()
Me.MyLabel3 = New System.Windows.Forms.Label()
Me.MyLabel4 = New System.Windows.Forms.Label()
Me.MyLabel5 = New System.Windows.Forms.Label()
Me.MyLabel6 = New System.Windows.Forms.Label()
Me.Label1 = New System.Windows.Forms.Label()
Me.Label2 = New System.Windows.Forms.Label()
Me.Panel2 = New System.Windows.Forms.Panel()
Me.MyLabel7 = New System.Windows.Forms.Label()
Me.Label4 = New System.Windows.Forms.Label()
Me.Label5 = New System.Windows.Forms.Label()

Here is a picture of my designer with the nested container controls. Also, a before and after picture of the form.

Preview of form designer and code results

Thraka
  • 2,065
  • 19
  • 24
0

Here is one method to iterate over all controls and modify the Textboxes. Has drawback that SplitterControl is skipped.

    Dim ctl As Control = Me ' top level seed
    Do
        If Not ctl.HasChildren Then
            If TypeOf ctl Is TextBox Then
                ctl.Text = ""
            End If
        End If
        ctl = Me.GetNextControl(ctl, True) ' does not reach into SpliterControls
    Loop Until ctl Is Nothing
rheitzman
  • 2,247
  • 3
  • 20
  • 36