C# Winforms控件添加到窗体时是否引发事件
我正在处理一些自定义的C# Winforms控件添加到窗体时是否引发事件,c#,winforms,events,custom-controls,C#,Winforms,Events,Custom Controls,我正在处理一些自定义的控件类,需要对它们进行一些初始化,这取决于它们是否被添加到表单中。发生这种情况时是否有触发的事件 我认为这个示例应该足以说明我正在尝试做什么: public interface IMyForm { ISomeObject SomeObject {get; set; } } class MyForm : IMyForm { //eg InitializeComponent() as well as several others called at later
控件
类,需要对它们进行一些初始化,这取决于它们是否被添加到表单中。发生这种情况时是否有触发的事件
我认为这个示例应该足以说明我正在尝试做什么:
public interface IMyForm
{
ISomeObject SomeObject {get; set; }
}
class MyForm : IMyForm
{
//eg InitializeComponent() as well as several others called at later points
private MethodThatAddsAControl()
{
MyControl newControl = new MyControl();
//other initialization as needed
//does this raise an event in MyControl I can use to call
//InitializationAfterBeingAddedToForm()?
this.Controls.Add(newControl);
}
}
class MyControl : Control
{
InitializationAfterBeingAddedToForm()
{
//can't be done in the constructor because at that point FindForm() will return null
(FindForm() as IMyForm).SomeObject.AnEvent += new EventHandler(SomeObject_AnEvent);
}
}
事实证明,这比我最初意识到的要困难得多,我想我必须结合博鲁和迈克·杜尔的建议。问题在于,当一些MyControl
s直接添加到表单中时,Bolu的解决方案可以完美地工作。其他内容将添加到面板中,而不是直接添加到表单中。我想我已经拼凑了一个解决方案,涉及到Bolu针对前一个案例的解决方案,并进行了一些修改,以处理由添加的面板而不是其中的MyControl
引发事件的情况,和Mikes来处理构造函数完成运行后将MyControl
s添加到面板的情况。明天早上,我必须对它进行更多的测试,然后才能确信它能起作用
当我尝试在设计器中使用Bolu的建议时,Bolu请求的错误消息:
未能创建组件“MyControl”。错误消息如下:
'System.MissingMethodException:找不到类型'MyNamespace.MyControl'的构造函数。
位于System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr、Binder Binder、Object[]args、CultureInfo区域性、Object[]ActivationAttribute)
在System.Activator.CreateInstance(类型类型、BindingFlags bindingAttr、Binder Binder、对象[]参数、CultureInfo区域性、对象[]ActivationAttribute)
位于System.ComponentModel.Design.DesignSurface.CreateInstance(类型)
位于Microsoft.VisualStudio.Design.VSDesignSurface.CreateInstance(类型)
位于System.ComponentModel.Design.DesignerHost.System.ComponentModel.Design.IDesignerHost.CreateComponent(类型componentType,字符串名称)
位于System.ComponentModel.Design.DesignerHost.System.ComponentModel.Design.IDesignerHost.CreateComponent(类型componentType)
位于System.Drawing.Design.ToolboxItem.CreateComponentsCore(IDesignerHost主机)
位于System.Drawing.Design.ToolboxItem.CreateComponentsCore(IDesignerHost主机,IDictionary默认值)
...'
当我发现错误时,构造器就就位了
public MyControl(Form parent)
{
_parent = parent as IMyForm;
parent.ControlAdded += new ControlEventHandler(parent_ControlAdded);
Initialize(); //does rest of initialization
}
public TimelineControl(Form parent, Panel container)
{
_parent = parent as IMyForm;
container.ControlAdded += new ControlEventHandler(parent_ControlAdded);
Initialize(); //does rest of initialization
}
尝试
ParentChanged
事件。为什么不在MyControl中实现自定义事件
本文介绍了该方法:
MyControl
myformpform代码>
MyForm
引用传递给MyControl
:
MyControl newControl=新的MyControl(此)ControlAdded
对象的MyForm
事件
pForm.ControlAdded+=新的ControlEventHandler(pForm\u ControlAdded)代码>
class MyForm : IMyForm
{
private MethodThatAddsAControl() //includes includes InitializeComponent as well as several others called at later
{
MyControl newControl = new MyControl(this);
//other initialization as needed
this.Controls.Add(newControl); //this will raise MyControl ::pForm_ControlAdded
}
}
class MyControl : Control
{
Myform pForm;
public MyControl(MyForm ff)
{
InitializeComponent();
pForm=ff;
pForm.ControlAdded+=new ControlEventHandler(pForm_ControlAdded);
}
}
编辑:
对于要添加到面板的MyControl,只需将面板的引用传递给MyControl:
class MyForm : IMyForm
{
private MethodThatAddsAControl() //includes includes InitializeComponent as well as several others called at later
{
//create a MyControl object and add it to MyForm
MyControl newControl = new MyControl(this);
//other initialization as needed
this.Controls.Add(newControl); //this will raise MyControl::pForm_ControlAdded
//create a MyControl object and add it to MyPanel1
MyControl newControl = new MyControl(MyPanel1); //pass panel reference
MyPanel1.Controls.Add(newControl); //this will raise MyControl::pPanel_ControlAdded
}
}
class MyControl : Control
{
//// for control added to Form
Myform pForm;
public MyControl(MyForm ff)
{
InitializeComponent();
pForm=ff;
pForm.ControlAdded+=new ControlEventHandler(pForm_ControlAdded);
}
///now for control added to panel
MyPanel pPanel;
public MyControl(MyPanel pp)
{
InitializeComponent();
pPanel=pp;
pPanel.ControlAdded+=new ControlEventHandler(pPanel_ControlAdded);
}
}
如果我这样做了,设计师是否足够聪明,可以自动将其传递给构造函数?我认为您的编辑不会起作用。我需要IMyForm,因为VS设计器在调用pPanel_ControlAdded时将面板添加到窗体之前会将控件添加到面板中,所以我没有办法获取窗体。实际上,如果我修改它以传递面板和将添加到的窗体,则会。设计师正在轰炸,错误似乎是它需要一个无参数构造函数,除非我遗漏了什么,否则会扼杀你的想法。那么你的MyControl构造函数是什么?您是否按照我上面的建议重写它以获取Mypanel和Myform引用?我无法重现错误。不管怎样,很高兴你从Mike那里得到了答案。此事件不适合,因为它需要设计师在添加面板之前将控件添加到面板中,然后再添加面板以形成其外观。这会导致ParentChanged在可以跟随父属性到表单对象之前触发。当父对象被设置时,您可以沿着当前父链,并沿途钩住每个父对象的
ParentChanged
事件。这样,您就可以知道任何祖先的父代何时发生更改。当父对象发生更改时,将所有您的ParentChanged
处理程序(要执行此操作,您必须在上一步的列表中存储所有钩住的控件),然后再次执行祖先漫游。我能够让它工作。因为我没有做任何会导致ParentChanged对每个控件触发多次的操作,所以如果不是我要查找的表单对象,我只会将相同的代码挂接到父链中最顶端的控件上。这很有意义。很高兴我能帮忙。因为已经有这样的活动了,请看公认的答案。哦,好吧,这是3年前的事了!