查找窗体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。

。不要把我推荐给旧的帖子,它显示了一个类似的功能,我的,只得到控件的列表。

编辑:为什么投反对票?这个问题以前从来没有人回答过!

查找窗体c#上的组件(不是控件)

令人惊讶的是,似乎唯一的方法就是通过反射。

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;
}