简体   繁体   English

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

[英]Find components on a windows form c# (not controls)

I know how to find and collect a list of all the controls used in a Windows Form.我知道如何查找和收集 Windows 表单中使用的所有控件的列表。 Something like this:是这样的:

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

However this function does not retrieve the non-visual components on the bottom of the form like the HelpProvider, ImageList, TableAdapters, DataSets, etc.然而,这个 function 不会检索表单底部的非可视组件,如 HelpProvider、ImageList、TableAdapters、DataSets 等。

Is there a way to get the list of these components as well?有没有办法获得这些组件的列表?

Edit:编辑:

Thanks @HighCore for pointing me to use System.ComponentModel.Component instead in a similar function does get me a list with components such the ImageList, the Help Provider and the BindingSource.感谢@HighCore 指点我在类似的 function 中使用 System.ComponentModel.Component 代替,确实让我得到了一个包含 ImageList、Help Provider 和 BindingSource 等组件的列表。 However, I still miss from this list the TableAdapters and the DataSets.但是,我仍然错过了此列表中的 TableAdapter 和 DataSet。 I suppose because those inherit directly from Object.我想是因为那些直接继承自 Object。

Please . Don't refer me to older posts which shows a similar function to mine and that only gets the list of the controls.不要让我参考显示与我的类似的 function 且仅获取控件列表的旧帖子。

Edit: Why the negative votes?编辑:为什么反对票? This question has never been answered before!这个问题以前从来没有人回答过!

Surprisingly, it seems the only way to do this is via reflection. 令人惊讶的是,似乎做到这一点的唯一方法是通过反射。

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

All controls built through the designer must have a private field called "components" of type IContainer. 通过设计器构建的所有控件都必须具有IContainer类型的私有字段,称为“组件”。 You can use reflection to get the value of this field, if it exists, and then iterate through the components. 您可以使用反射来获取此字段的值(如果存在),然后遍历组件。

This method differs from the other answer in that this will only return the components added to the form using the designer, as opposed to all fields that can be cast as Component. 此方法与其他答案的不同之处在于,这将仅返回使用设计器添加到表单的组件,而不是可以转换为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>();
        }
    }

There is a cleaner way than Reflection to get components from a form.有一种比反射更简洁的方法从表单中获取组件。 The form itself is a component holder, so it is good that it implements IContainer, as such, I don't even understand why it wasn't done that way.表单本身是一个组件持有者,所以它实现 IContainer 是件好事,因此,我什至不明白为什么没有那样做。

After casting it into an IContainer, not only will you be able to retrieve all the components generated by the designer, but as a bonus, you will also be able to add/remove your own components, obeying the Form Dispose() mechanism.将其转换为 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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM