【问题标题】:Find components on a windows form c# (not controls)在 Windows 窗体 c# 上查找组件(不是控件)
【发布时间】:2013-06-14 20:19:29
【问题描述】:

我知道如何查找和收集 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、Help Provider 和 BindingSource 等组件的列表。 但是,我仍然从这个列表中错过了 TableAdapters 和 DataSets。我想是因为那些直接继承自 Object。

。不要让我参考显示与我的功能相似且仅获取控件列表的旧帖子。

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

【问题讨论】:

  • 我不熟悉winforms,但如果你要找的是Components(即System.ComponentModel.Component),你应该使用它而不是Control。顺便说一句,请把这个可怕的 foreach 代码改成漂亮的.SelectMany()
  • @HighCore SelectMany 的使用在这里并没有那么有用。主要问题是,从设计的角度来看,它将结果添加到作为参数传入的列表中,而不是作为结果产生它们。如果需要,您还可以删除递归并使用显式堆栈。不过,在这里使用foreach 并不是不合适的。
  • 不,这与您指出的内容不重复。我要求的是非视觉组件,而不是控件。该帖子上的问题提到了“组件”,但解决方案仅解决了获取控件列表。

标签: c# winforms visual-studio-2012 controls components


【解决方案1】:

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

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

【讨论】:

  • 对不起,我知道这个线程很旧,但我很惊讶这是获取表单组件的唯一(而且不是那么直观)的方法。感谢克雷格的问题和迈克尔的回答。这对我帮助很大。
  • @Smith 取决于您要递归的内容。组件的组成部分?子控件的组件?自有窗口的组件?
  • @MichaelGunter menuitems, toolstripbuttons, buttons, labels, textboxes, columnheaders 等基本上,任何可以本地化文本的控件
  • @Smith 可能有一种方法可以枚举 所有 可设计的组件(就像 Visual Studio 本身所做的那样),但它会很复杂且容易出错。如果你想枚举设计器中所有有名字的东西,你可以做我在这个答案中展示的同样的事情——只需删除where 子句和转换为(Component)
  • @MichaelGunter 有没有办法在 DesignTime (WinForms) 期间让它工作?
【解决方案2】:

通过设计器构建的所有控件都必须有一个名为“组件”的 IContainer 类型的私有字段。您可以使用反射来获取该字段的值(如果存在),然后遍历组件。

此方法与其他答案的不同之处在于,它只会返回使用设计器添加到表单的组件,而不是可以转换为组件的所有字段。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-27
    • 2011-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多