在用户控件中解释自定义事件的代码

有人给了我这个效果很好的代码。 但我真的很想了解其中发生的事情。 有人可以解释一下吗? 代码的每个部分的含义是什么? 代码位于自定义控件内,该控件在面板内有两个标签。

此外,我已经看到一些使用添加/删除语法的自定义控件事件,这是为了什么? 与这里发生的事情有什么不同?

public partial class UserControl1 : UserControl { public UserControl1() { InitializeComponent(); } public event EventHandler MyCustomClickEvent; protected virtual void OnMyCustomClickEvent(EventArgs e) { // Here, you use the "this" so it's your own control. You can also // customize the EventArgs to pass something you'd like. if (MyCustomClickEvent != null) MyCustomClickEvent(this, e); } private void label1_Click(object sender, EventArgs e) { OnMyCustomClickEvent(EventArgs.Empty); } } 

请参阅下面的评论。 另外,对于更详细的事件,我在这个概念的博客上回顾了整个过程的更多细节。

 public partial class UserControl1 : UserControl { //This is the standard constructor of a user control public UserControl1() { InitializeComponent(); } //This defines an event called "MyCustomClickEvent", which is a generic //event handler. (EventHander is a delegate definition that defines the contract //of what information will be shared by the event. In this case a single parameter //of an EventArgs object. public event EventHandler MyCustomClickEvent; //This method is used to raise the event, when the event should be raised, //this method will check to see if there are any subscribers, if there are, //it raises the event protected virtual void OnMyCustomClickEvent(EventArgs e) { // Here, you use the "this" so it's your own control. You can also // customize the EventArgs to pass something you'd like. if (MyCustomClickEvent != null) MyCustomClickEvent(this, e); } private void label1_Click(object sender, EventArgs e) { OnMyCustomClickEvent(EventArgs.Empty); } } 

我建议在MSDN上阅读C#上的事件 。 详细介绍了这一点。

基本上, MyCustomClickEvent是一个事件。 OnMyCustomClickEvent方法用于引发事件,但是如果需要,子类也可以引发此事件。

单击“label1”时,将运行OnMyCustomClickEvent方法,从而引发事件。 订阅该事件的任何代表都将在该点执行。

您提到在某些自定义控件示例中看到事件的添加/删除语法。 很可能这些示例使用UserControl类的Events属性来存储事件处理程序,例如在以下示例中:

  public event EventHandler MyEvent { add { Events.AddHandler("MyEvent", value); } remove { Events.RemoveHandler("MyEvent", value); } } 

这样的想法通常是控件的消费者不想要处理控件公开的每个事件。 如果每个事件都被定义为“字段”事件(如您的示例所示),那么即使该事件没有订阅者,每个事件也会占用一块内存。 当您有一个由数百个控件构成的复杂页面时,每个控件可能有几十个事件,未使用事件的内存消耗并不是无关紧要的。

这就是System.ComponentModel.Component类( System.Windows.Forms.Control类的基类)具有Events属性的原因,该属性基本上是用于存储事件处理程序委托的字典。 这样,每个事件的实现更像是属性而不是字段。 每个事件的添加/删除处理程序存储或从Events字典中删除委托。 如果未使用事件,则Events字典中没有条目,并且不会为该事件消耗额外的内存。 做一些工作(必须查找事件处理程序)以节省更多内存是一种权衡。

编辑:修复我的答案与Windows窗体,而不是ASP.NET,虽然概念是相同的。

关于添加/删除,这是事件的“手动”实现。 以下两个片段做同样的事情。

自动实施:

 public event EventHandler MyEvent; 

手动实施:

 private EventHandler _myEvent; public event EventHandler MyEvent { add { _myEvent += value; } remove { _myEvent -= value; } } 

这与自动属性完全相同,其中:

 public string Property { get; set; }; 

完全相同:

 private string _property; public string Property { get { return _property; } set { _property = value; } } 

这些片段之间的区别在于,通过手动实现,您可以获得更多控制权。 例子是:

  • 在add / get和remove / set中实现逻辑;
  • 访问允许您设置例如[NonSerializable]的字段;
  • 将值放在例如Dictionary

Form类例如执行后者以保持Form类中字段的数量。