Is there a way to iterate through all the controls in my project?

I would like to know if there is a way to iterate through all the controls in my project. Be them on a WinForm, or on an UserControl, even if they're not loaded. I would like to do this so I can get the .Tag property for every control, along with its name and parent.

What I have so far is that I can get every type in My namespace, but from there I don't know what to do.

Private Function GetTypesInNamespace(ByVal assembly As Assembly, ByVal [nameSpace] As String) As Type()
    Return assembly.GetTypes().Where(Function(t) String.Equals(t.[Namespace], [nameSpace], StringComparison.Ordinal)).ToArray()
End Function

Upvotes: 2

Views: 617

Answers (1)

djv
djv

Reputation: 15772

I'm going to ignore Namespace for this. You can add it if you like. But this function does what your function purported to do.

Public Function getAllTypesOfControl(assembly As Assembly) As IEnumerable(Of Type)
    Return assembly.GetTypes().
        Where(Function(t) t.IsSubclassOf(GetType(ContainerControl))).
        SelectMany(Function(container) container.GetFields(BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public)).
        Where(Function(f) f.FieldType.IsSubclassOf(GetType(Control))).
        Select(Function(f) f.FieldType)
End Function

Now, you are left with all the Types of all the Controls which are defined in Controls which are ContainerControls. This should include controls defined inside Forms and UserControls, as you mentioned.

Can you do something with this? I don't think so, since you are hoping to access instances of controls. To do this, you shouldn't be dealing in the regime of Assembly, rather your runtime, which should have your instantiated controls. I think?

You may want to look at Application.OpenForms, and iterate all open forms, and return all controls.

Public Function getAllInstantiatedControls() As IEnumerable(Of Control)
    Return Application.OpenForms.Cast(Of Form).
        SelectMany(Function(openForm) openForm.Controls.Cast(Of Control)().
            Select(Function(c) c.Controls.Cast(Of Control).Append(c))).
        SelectMany(Function(c) c)
End Function

You probably want the second one, because you can't just purely act on Types, as I understand you want to store controls properties. So let me break down your problem. You said

...[components in forms] are stored in my project and i can easly see / modify their details...

yes, but do you know how those details are stored? In fact, they are not stored, but set when the form is constructed. Actually, Visual Studio needs to run InitializeComponent in order to show you the designer - every time you make a change to a control. So the details are in fact stored like this (in the designer code, Form1.Designer.vb) with a Button named Button1 on it.

Design

enter image description here

Form1.Designer.vb

Partial Class Form1
    Inherits System.Windows.Forms.Form

    Public Sub New()
        InitializeComponent()
    End Sub

    Private Sub InitializeComponent()
        ' ...
        Me.Button1 = New System.Windows.Forms.Button()
        '
        'Button1
        '
        Me.Button1.Location = New System.Drawing.Point(157, 103)
        Me.Button1.Name = "Button1"
        Me.Button1.Size = New System.Drawing.Size(75, 23)
        Me.Button1.TabIndex = 3
        Me.Button1.Text = "Button1"
        Me.Button1.UseVisualStyleBackColor = True
        '
        'Form1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(203, 114)
        Me.Controls.Add(Me.Button1)
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.ResumeLayout(False)
    End Sub

    Friend WithEvents Button1 As Button
End Class

You can modify or delete that button and watch the code change or disappear from Form1.Designer.vb. So your "details" are stored in code. This is what the "Visual" in Visual Basic means behind the scenes.

So these details are only set when you run InitializeComponent, which means they are set two ways:

  1. In Visual Studio Form1 Design view
  2. When an application is run and a Form1 instance is created

Other than these two ways, the control properties do NOT have your values, and would only have default values (but this is really an impossible situation and of dubious relevance).

Knowing this, you must access the instances of controls, which is achieved with the Application.OpenForms option. I think you can load all controls, and write to some settings file or database, and also read back and find controls and update them based on the settings file or database. I'm not writing that though. I think I answered your question.

Upvotes: 1

Related Questions