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
CodePudding user response:
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?
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:
- In Visual Studio Form1 Design view
- 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.