有没有办法遍历我项目中的所有控件?
Is there a way to iterate through all the controls in my project?
我想知道是否有一种方法可以遍历我项目中的所有控件。无论是在 WinForm 上还是在 UserControl 上,即使它们没有加载。我想这样做,这样我就可以获得每个控件的 .Tag
属性,以及它的名称和父级。
到目前为止,我可以获取我的命名空间中的所有类型,但我不知道从那里可以做什么。
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
为此我将忽略命名空间。如果你喜欢,你可以添加它。但是这个函数完成了你的函数声称要做的事情。
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
现在,您剩下的是在 ContainerControls 中定义的所有控件的所有类型。正如您提到的,这应该包括在 Forms 和 UserControls 中定义的控件。
你能用这个做点什么吗?我不这么认为,因为您希望访问控件的 实例 。要做到这一点,您不应该处理 Assembly 的机制,而是您的 运行time,它应该有您的实例化控件。我觉得?
您可能想要查看 Application.OpenForms,并迭代所有打开的表单和 return 所有控件。
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
您可能想要第二个,因为您不能只对类型进行操作,据我了解您想要存储控件属性。所以让我分解你的问题。
...[components in forms] are stored in my project and i can easly see / modify their details...
是的,但是您知道这些详细信息是如何存储的吗?实际上,它们并没有被存储,而是在构造表单时设置的。实际上,Visual Studio 需要 运行 InitializeComponent
才能向您展示设计器 - 每次您对控件进行更改时。所以细节实际上是这样存储的(在设计器代码中,Form1.Designer.vb)上面有一个名为 Button1 的按钮。
设计
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
您可以修改或删除该按钮并观察代码从 Form1.Designer.vb 中更改或消失。因此,您的“详细信息”存储在代码中。这就是 Visual Basic 中的“Visual”在幕后的含义。
所以这些细节仅在您 运行 InitializeComponent 时设置,这意味着它们有两种设置方式:
- 在 Visual Studio Form1 设计视图中
- 当应用程序 运行 并且创建了 Form1 实例时
除了这两种方式,控件属性没有您的值,只有默认值(但这确实是不可能的情况,并且相关性可疑)。
知道这一点,您必须访问控件的实例,这是通过 Application.OpenForms 选项实现的。我认为您可以加载所有控件,写入某些设置文件或数据库,还可以回读并找到控件并根据设置文件或数据库更新它们。我不是在写那个。我想我回答了你的问题。
我想知道是否有一种方法可以遍历我项目中的所有控件。无论是在 WinForm 上还是在 UserControl 上,即使它们没有加载。我想这样做,这样我就可以获得每个控件的 .Tag
属性,以及它的名称和父级。
到目前为止,我可以获取我的命名空间中的所有类型,但我不知道从那里可以做什么。
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
为此我将忽略命名空间。如果你喜欢,你可以添加它。但是这个函数完成了你的函数声称要做的事情。
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
现在,您剩下的是在 ContainerControls 中定义的所有控件的所有类型。正如您提到的,这应该包括在 Forms 和 UserControls 中定义的控件。
你能用这个做点什么吗?我不这么认为,因为您希望访问控件的 实例 。要做到这一点,您不应该处理 Assembly 的机制,而是您的 运行time,它应该有您的实例化控件。我觉得?
您可能想要查看 Application.OpenForms,并迭代所有打开的表单和 return 所有控件。
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
您可能想要第二个,因为您不能只对类型进行操作,据我了解您想要存储控件属性。所以让我分解你的问题。
...[components in forms] are stored in my project and i can easly see / modify their details...
是的,但是您知道这些详细信息是如何存储的吗?实际上,它们并没有被存储,而是在构造表单时设置的。实际上,Visual Studio 需要 运行 InitializeComponent
才能向您展示设计器 - 每次您对控件进行更改时。所以细节实际上是这样存储的(在设计器代码中,Form1.Designer.vb)上面有一个名为 Button1 的按钮。
设计
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
您可以修改或删除该按钮并观察代码从 Form1.Designer.vb 中更改或消失。因此,您的“详细信息”存储在代码中。这就是 Visual Basic 中的“Visual”在幕后的含义。
所以这些细节仅在您 运行 InitializeComponent 时设置,这意味着它们有两种设置方式:
- 在 Visual Studio Form1 设计视图中
- 当应用程序 运行 并且创建了 Form1 实例时
除了这两种方式,控件属性没有您的值,只有默认值(但这确实是不可能的情况,并且相关性可疑)。
知道这一点,您必须访问控件的实例,这是通过 Application.OpenForms 选项实现的。我认为您可以加载所有控件,写入某些设置文件或数据库,还可以回读并找到控件并根据设置文件或数据库更新它们。我不是在写那个。我想我回答了你的问题。