查找窗体c#上的组件(不是控件)
本文关键字:控件 组件 窗体 查找 | 更新日期: 2023-09-27 18:18:58
我知道如何查找和收集Windows窗体中使用的所有控件的列表。像这样:
static public void FillControls(Control control, List<Control> AllControls)
{
String controlName = "";
controlName = control.Name;
foreach (Control c in control.Controls)
{
controlName = c.Name;
if ((control.Controls.Count > 0))
{
AllControls.Add(c);
FillControls(c, AllControls);
}
}
}
然而,这个函数不检索表单底部的非可视组件,如HelpProvider、ImageList、TableAdapters、DataSets等。
是否有一种方法可以获得这些组件的列表?
编辑:感谢@HighCore指向我使用System.ComponentModel.Component,而不是在一个类似的功能中,让我得到一个包含ImageList,帮助提供者和BindingSource等组件的列表。然而,我仍然错过了这个列表中的TableAdapters和DataSets。我想是因为它们直接继承了Object。
请。不要把我推荐给旧的帖子,它显示了一个类似的功能,我的,只得到控件的列表。
编辑:为什么投反对票?这个问题以前从来没有人回答过!
令人惊讶的是,似乎唯一的方法就是通过反射。
private IEnumerable<Component> EnumerateComponents()
{
return from field in GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
where typeof (Component).IsAssignableFrom(field.FieldType)
let component = (Component) field.GetValue(this)
where component != null
select component;
}
所有通过设计器构建的控件都必须有一个名为"components"的私有字段,类型为IContainer。您可以使用反射来获取该字段的值(如果存在),然后遍历组件。
此方法与其他答案的不同之处在于,它将只返回使用设计器添加到表单中的组件,而不是可以转换为Component的所有字段。
public IEnumerable<Component> GetComponents(Control c)
{
FieldInfo fi = c.GetType()
.GetField("components", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (fi?.GetValue(c) is IContainer container)
{
return container.Components.OfType<Component>();
}
else
{
return Enumerable.Empty<Component>();
}
}
要从表单中获取组件,有一种比反射更干净的方法。表单本身是一个组件持有人,所以它很好,它实现了IContainer,因此,我甚至不明白为什么不这样做。
在将其强制转换为IContainer之后,您不仅可以检索由设计器生成的所有组件,而且还可以添加/删除自己的组件,遵循Form Dispose()机制。
public partial class MyForm : Form, IContainer
{
// ...
public void Add(IComponent component) => this.components.Add(component);
public void Add(IComponent component, string name) => this.components.Add(component, name);
public void Remove(IComponent component) => this.components.Remove(component);
public ComponentCollection Components => components.Components;
}