我知道如何查找和收集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,DataSet等。
有没有办法获取这些组件的列表?
修改
感谢@HighCore指示我在类似的函数中使用System.ComponentModel.Component确实为我提供了一个包含ImageList,Help Provider和BindingSource等组件的列表。 但是,我仍然从这个列表中错过了TableAdapters和DataSet。我想因为那些直接从Object继承。
请即可。不要将我引用到显示与我的功能类似的旧帖子,并且只获取控件列表。
编辑:为什么负面投票?这个问题以前从未得到过回答!
答案 0 :(得分:16)
令人惊讶的是,似乎唯一的方法就是通过反思。
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;
}
答案 1 :(得分:0)
通过设计器构建的所有控件都必须具有一个名为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>();
}
}