一般枚举 .Net 控件的项目(MenuStrip、ToolStrip、StatusStrip)
我有一些代码,通常会获取表单中的所有控件并将它们放入列表中。 以下是一些代码:
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) 但我希望不必进行特定的类型测试。
如果我需要提供更多信息,请询问。
非常感谢
I've got some code that will generically get all Controls in a form and put them in a list. Here's some of the code:
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);
//
}
}
So I'm only able to use c.HasChildren to check and see if there's any more child controls from this root control.
What about a menuStrip, toolStrip, and statusStrip? How do I get all of the controls that are in these controls generically? Ex: MenuStripItem
I know that I could try testing the c.GetType() == typeof(MenuStrip) but I was hoping to not have to do specific type tests.
If I need to give more info, please ask.
Thanks a bunch
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我相信 VS 设计器是通过获取控件设计器的实例来实现的(请参阅
Designer
属性),并且,如果设计器是ComponentDesigner
,获取AssociatedComponents
属性。编辑:
好吧,我想这有点含糊。 但警告:接下来的内容有点复杂,可能不值得付出努力。
关于命名法的注释:
下面,我将提到 Visual Studio 中的设计器(该名称用于指代 Visual Studio 中的功能,通过该功能可以直观地编辑窗体和控件的布局和内容)以及设计器类(将对此进行解释)以下。 为了防止在任何给定时间对我所指的内容产生混淆,我将始终将 Visual Studio 中的设计器功能称为“设计器”,并将始终将设计器类称为“IDesigner”,它是每个接口都必须实现。
当 Visual Studio 设计器加载组件(通常是控件,但也包括 Timer 等)时,它会在
DesignerAttribute
类型的类上查找自定义属性。 (那些不熟悉属性的人可能需要阅读它们 在继续之前。)此属性(如果存在)提供类的名称(IDesigner),设计者可以使用它与组件进行交互。 实际上,此类控制设计器和组件的设计时行为的某些方面。 使用 IDesigner 确实可以做很多事情,但现在我们只对一件事感兴趣。
大多数使用自定义 IDesigner 的控件都使用派生自
ControlDesigner
的控件,而 ControlDesigner 本身又派生自ComponentDesigner
。ComponentDesigner
类有一个名为AssociatedComponents
的公共虚拟属性,该属性应在派生类中重写,以返回对该类的所有“子”组件的引用集合。更具体地说,
ToolStrip
控件(通过继承,MenuStrip
控件)有一个DesignerAttribute
,它引用名为ToolStripDesigner 的类
。 它看起来有点像:ToolStripDesigner
类不是公共的。 它位于 System.Design.dll 的内部。 但由于它是通过其完全限定名称在此处指定的,因此 VS 设计者无论如何都可以使用 Activator.CreateInstance 来创建它的实例。这个
ToolStripDesigner
类,因为它[间接]继承自ComponentDesigner
,所以有一个AssociatedComponents
属性。 当您调用它时,您将获得一个新的ArrayList
,其中包含对已添加到ToolStrip
中的所有项目的引用。那么,要完成同样的事情,您的代码必须是什么样子呢? 相当复杂,但我想我有一个有效的例子:
I believe the VS designer does it by getting an instance of the control's designer (see the
Designer
attribute), and, if the designer is aComponentDesigner
, getting theAssociatedComponents
property.EDIT:
Okay, I guess that's a little vague. A warning, though: what follows is a little complicated, and might not be worth the effort.
A note on nomenclature:
Below, I will be referring to both the designer within Visual Studio—which is the name used to refer to the functionality within Visual Studio by which the layout and content of forms and controls are edited visually—and to designer classes—which will be explained below. To prevent confusion as to which I am referring to at any given time, I will always refer to the designer functionality within Visual Studio as "the designer", and I will always refer to a designer class as an "IDesigner", which is the interface each must implement.
When the Visual Studio designer loads a component (usually a control, but also things like
Timer
and such), it looks for a custom attribute on the class of typeDesignerAttribute
. (Those unfamiliar with attributes might want read up on them before continuing.)This attribute, if present, provides the name of a class—an IDesigner—the designer can use to interface with the component. In effect, this class controls certain aspects of the designer and of the design-time behavior of the component. There's indeed quite a lot you can do with an IDesigner, but right now we're only interested in one thing.
Most controls that use a custom IDesigner use one that derives from
ControlDesigner
, which itself derives fromComponentDesigner
. TheComponentDesigner
class has a public virtual property calledAssociatedComponents
, which is meant to be overridden in derived classes to return a collection of references to all "child" components of this one.To be more specific, the
ToolStrip
control (and by inheritance, theMenuStrip
control) has aDesignerAttribute
that references a class calledToolStripDesigner
. It looks sort of like:The
ToolStripDesigner
class is not public. It's internal to System.Design.dll. But since it's specified here by it's fully qualified name, the VS designer can useActivator.CreateInstance
to create an instance of it anyway.This
ToolStripDesigner
class, because it inherits [indirectly] fromComponentDesigner
has anAssociatedComponents
property. When you call it you get a newArrayList
that contains references to all the items that have been added to theToolStrip
.So what would your code have to look like to do the same thing? Rather convoluted, but I think I have a working example:
ToolStripItem 等项目实际上并不是控件,它们只是组成 ToolStrip 或 MenuStrip 的组件。
这意味着,如果您想将这些组件包含在扁平化的控件列表中,那么您将需要进行特定的检查。
The items such as ToolStripItem etc aren't actually controls, they are simply components that make up a ToolStrip or MenuStrip.
Which means, that if you want to include those components in your flattened list of controls then you will need to do the specific checks.
ToolStripControlHost 可能包含一个 Control:
...也就是说,如果您将参数 1 更改为类型
IEnumerable
并编写自己的 EnumerateTree 函数(我认为拥有一个好的函数很棒通用 EnumerateTree 方法)。ToolStripControlHost might contain a Control:
...that's if you change argument 1 to type
IEnumerable<Control>
and write your own EnumerateTree function (I think it's great to have one good generic EnumerateTree method).