在Visual Studio中创建表单时,Designer会自动生成组件容器:
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
我们有几十种表单,所有表单共享一个公共基类,以便轻松放入一些常用功能(“您有未保存的数据,您确定要关闭此窗口吗?”等等) 。每个表单都有自己的BarManager组件(它们有不同的菜单和按钮等等,因此没有人认为需要让它们继承该组件)。现在我们已经意识到我们想要为所有BarManagers添加一个事件处理程序。
我希望能够做到这样的事情:
public partial class Foo : Form
{
...
private void Foo_Shown(object sender, EventArgs e)
{
this.components.Components.OfType<BarManager>().ToList().ForEach(tb =>
{
tb.SomeEvent += new EventHandler(FooHandler);
});
}
protected void FooHandler(object sender, EventArgs e)
{
// do stuff
}
...
}
如果它在Controls
集合中,该方法可以正常工作,但由于components
是私有的,Foo&amp;它的控件有单独的集合。
有没有办法在不修改每个子类的情况下实现这一目标?我怀疑它可以通过反射(我不是很熟悉)来完成,但如果可能的话,我更喜欢没有反射的解决方案。
答案 0 :(得分:1)
由于设计者将components
变量生成为私有,因此反射是唯一的方法。当然,你可以很聪明,并确保只使用一次反射来获取你将使用你的变量指向的实例,这样后续访问将更有效。
你可以制作自己的设计师代码序列化器,但我认为这有点过分。另外,这不会使现有的表单组件变量更加可用(除非您为每个组件重新打开设计器)。
如果我可以:因为每个表单只有一个工具栏(或者看起来好像?),为什么不递归地浏览表单的控件集合,直到找到它的实例?
修改强>
由于您使用的是DexExpress,因此您的表单会将DevExpress.XtraBars.BarDockControl
个实例作为控件放在表单中。它们充当组件工具栏对象的容器。在Form.Controls
中查找运行时的那些。他们有一个Manager
属性,可以为您提供他们所附加的酒吧经理。当然,从那里你可以访问它包含的每个工具栏。