我创建了一个包含自定义组件的 WinForms 应用程序。
组件需要在启动时触发其中一个事件,但是在调用组件的构造函数时,所有事件处理程序仍然为空。
我需要的是一个事件,它告诉我拥有该组件的窗口已加载并且所有事件处理程序都已设置。
但是,组件似乎没有Load
事件。事实上,除了活动之外,它们似乎根本没有任何活动Disposed
。
我的组件如何知道何时可以安全地在启动时触发事件?
我创建了一个包含自定义组件的 WinForms 应用程序。
组件需要在启动时触发其中一个事件,但是在调用组件的构造函数时,所有事件处理程序仍然为空。
我需要的是一个事件,它告诉我拥有该组件的窗口已加载并且所有事件处理程序都已设置。
但是,组件似乎没有Load
事件。事实上,除了活动之外,它们似乎根本没有任何活动Disposed
。
我的组件如何知道何时可以安全地在启动时触发事件?
一种可能的解决方案是在组件连接到侦听器时触发事件。您需要创建自己的事件属性。
class MyClass
{
private static readonly _myEvent = new object();
private EventHandlerList _handlers = new EventHandlerList();
public event EventHandler MyEvent
{
add
{
_handlers.AddHandler(_myEvent, value);
OnMyEvent(); // fire the startup event
}
remove { _handlers.RemoveHandler(_myEvent, value); }
}
private void OnMyEvent()
{
EventHandler myEvent = _handlers[_myEvent] as EventHandler;
if (myEvent != null) myEvent(this, EventArgs.Empty);
}
...
}
至少有2种不同的方式。
第一种方法是在设计时使用站点跟踪容器(运行时不调用站点)。它只是在设计时保存 ContainerControl 属性,因此在运行时可以使用它。您可以在框架的某些组件的属性浏览器中看到它。
private ContainerControl _containerControl;
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public ContainerControl ContainerControl
{
get { return _containerControl; }
set
{
_containerControl = value;
if (DesignMode || _containerControl == null)
return;
if (_containerControl is Form)
((Form) _containerControl).Load += (sender, args) => { Load(); };
else if (_containerControl is UserControl)
((UserControl)_containerControl).Load += (sender, args) => { Load(); };
else
System.Diagnostics.Debug.WriteLine("Unknown container type. Cannot setup initialization.");
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Browsable(false)]
public override ISite Site
{
get { return base.Site; }
set
{
base.Site = value;
if (value == null)
return;
IDesignerHost host = value.GetService(typeof(IDesignerHost)) as IDesignerHost;
if (host == null)
return;
IComponent componentHost = host.RootComponent;
if (componentHost is ContainerControl)
ContainerControl = componentHost as ContainerControl;
}
}
private void Load()
{
}
第二种方法是在Component中实现ISupportInitialize。在这种情况下,Visual Studio (2013) 在设计时生成调用组件上的 ISupportInitialize 方法(BeginInit 和 EndInit)的代码。