一般枚举.Net控件的项目(MenuStrip,ToolStrip,StatusStrip)

时间:2008-11-17 23:23:52

标签: c# .net-2.0

我有一些代码,通常会在表单中获取所有控件并将它们放在列表中。这是一些代码:

        private List<Control> GetControlList(Form parentForm)
        {
            List<Control> controlList = new List<Control>();
            AddControlsToList(parentForm.Controls, controlList);

            return controlList;
        }

        private void AddControlsToList(Control.ControlCollection rootControls, List<Control> controlList)
        {
            foreach (Control c in rootControls)
            {
                controlList.Add(c);
                if (c.HasChildren)
                    AddControlsToList(c.Controls, controlList);
                //
            }
        }

所以我只能使用c.HasChildren检查并查看是否还有来自此根控件的子控件。

menuStrip,toolStrip和statusStrip怎么样?如何获得这些控件中的所有控件?例如:MenuStripItem

我知道我可以尝试测试c.GetType()== typeof(MenuStrip),但我希望不必进行特定的类型测试。

如果我需要提供更多信息,请询问。

非常感谢

3 个答案:

答案 0 :(得分:6)

我相信VS设计师通过获取控件设计器的实例(参见Designer attribute)来实现它,如果设计者是ComponentDesigner,则获得AssociatedComponents属性。

修改

好吧,我猜这有点模糊。但是有一个警告:接下来的内容有点复杂,可能不值得付出努力。

关于命名法的说明:
下面,我将引用Visual Studio中的设计器 - 这是用于引用Visual Studio中的功能的名称,通过它可以直观地编辑表单和控件的布局和内容,以及设计器类 - 这将被解释下面。为了防止在任何给定时间引起混淆,我将始终将Visual Studio中的设计器功能称为“设计器”,并且我将始终将设计器类称为“IDesigner”,这是每个界面都必须实现。

当Visual Studio设计器加载一个组件(通常是一个控件,还有Timer之类的东西)时,它会在类型DesignerAttribute的类上查找自定义属性。 (那些不熟悉属性的人在继续之前可能需要read up on them。)

此属性(如果存在)提供类的名称 - 一个IDesigner - 设计人员可以使用该名称与组件进行交互。实际上,此类控制设计器的某些方面以及组件的设计时行为。你可以用IDesigner做很多事情,但是现在我们只对一件事感兴趣。

使用自定义IDesigner的大多数控件都使用派生自ControlDesigner的控件,该控件本身派生自ComponentDesignerComponentDesigner类有一个名为AssociatedComponents的公共虚拟属性,它在派生类中被覆盖,以返回对此节点的所有“子”组件的引用集合。

更具体地说,ToolStrip控件(以及继承,MenuStrip控件)有DesignerAttribute引用名为ToolStripDesigner的类。看起来有点像:

/*
 * note that in C#, I can refer to the "DesignerAttribute" class within the [ brackets ]
 * by simply "Designer".  The compiler adds the "Attribute" to the end for us (assuming
 * there's no attribute class named simply "Designer").
 */
[Designer("System.Windows.Forms.Design.ToolStripDesigner, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), ...(other attributes)]
public class ToolStrip : ScrollableControl, IArrangedElement, ...(other interfaces){
    ...
}

ToolStripDesigner课程不公开。它是System.Design.dll的内部。但由于它是由完全限定名称指定的,因此VS设计人员无论如何都可以使用Activator.CreateInstance来创建它的实例。

ToolStripDesigner类,因为它从[{1}}继承[间接]具有ComponentDesigner属性。当您调用它时,您会收到一个新的AssociatedComponents,其中包含对已添加到ArrayList的所有项目的引用。

那么你的代码必须看起来像做同样的事情?相当复杂,但我想我有一个有效的例子:

ToolStrip

答案 1 :(得分:0)

ToolStripItem等项目实际上不是控件,它们只是构成ToolStrip或MenuStrip的组件。

这意味着,如果您想将这些组件包含在展平的控件列表中,那么您需要进行特定的检查。

答案 2 :(得分:0)

ToolStripControlHost可能包含Control:

if (c is ToolStrip)
    foreach (ToolStripItem item in EnumerateTree(c, "Items"))
        if (item is ToolStripControlHost)
            AddControlsToList(
                new Control[] { ((ToolStripControlHost)item).Control },
                controlList);

...如果您将参数1更改为IEnumerable<Control>类型并编写自己的EnumerateTree函数(我认为很好有一个好的通用EnumerateTree方法)。