一.什么是事件
事件涉及两类角色——事件的发布者和事件的订阅者,当某个事件发生后,事件发布者会发布消息;事件订阅者会接收到事件已发生的通知,并做出相应处理。其中,触发事件的对象成为事件发布者,捕获事件并对其做出处理的对象成为事件订阅者。
二.如何定义事件
在C#中定义事件,与定义类成员非常相似,仅需要另外包含一个event关键字即可,如下所示:
public evnet EvnetHandler birthday
事件的定义结构为:
访问修饰符 event 委托类型 事件名;
事件定义中还包含委托类型,它既可以是自定义的委托类型,也可以是.NET类库中预定义的委托类型EventHandler。
三.订阅和取消事件
事件订阅者需要订阅事件发布者发布的事件,以便在事件被触发时接收到消息并做出处理;可以使用“+=”运算符来订阅事件,使用“-=”运算符来取消事件订阅。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Evnet { //新郎官类充当事件的发布者角色 public class BridegRoom { //自定义委托 public delegate void MarryHandler(string msg); //使用自定义委托类型定义事件,事件名为MarryEvent public event MarryHandler MarryEvent; //发出事件 public void OnMarriageComing(string msg) { //判断是否绑定了事件处理方法 if(MarryEvent != null) { //触发事件 MarryEvent(msg); } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Evnet { //朋友类,事件订阅者 public class Friend { //字段 public string _name; //构造函数 public Friend(string name) { _name = name; } //事件处理函数,该函数需要符合MarryHandler委托的定义 public void SendMessage(string message) { //输出通知信息 Console.WriteLine(message); //对事件做出处理 Console.WriteLine(this._name + "收到了,到时候准时参见"); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Evnet { class Program { public event EventHandler e; static void Main(string[] args) { //初始化新郎官对象 BridegRoom br = new BridegRoom(); //实例化朋友对象 Friend f1 = new Friend("陈三"); Friend f2 = new Friend("李四"); Friend f3 = new Friend("王五"); //使用“+=”来订阅事件 br.MarryEvent += new BridegRoom.MarryHandler(f1.SendMessage); br.MarryEvent += new BridegRoom.MarryHandler(f2.SendMessage); //发出通知,此时只有订阅了事件的对象才能收到通知 br.OnMarriageComing("朋友们,我结婚了,到时候准时参加婚礼!"); Console.WriteLine("---------------------------------------"); //使用“-=”来取消事件的订阅,此时李四收不到信息 br.MarryEvent -= new BridegRoom.MarryHandler(f2.SendMessage); //使用“+=”来取消订阅事件,此时王五可以收到通知 br.MarryEvent += new BridegRoom.MarryHandler(f3.SendMessage); //发出通知 br.OnMarriageComing("朋友们,我结婚了,到时候准时参加婚礼!"); Console.ReadKey(); } } }
四.使用.NET类库汇总预定义的委托类型EventHandler来定义事件
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyEventHandler { //新郎官类,事件发布者角色 public class BridegRoom { //使用.NET类库中预定义的委托类型EventHandler来定义事件 public event EventHandler MarryEvent; //发出事件 public void OnBirthdayComing(string msg) { //判断是否绑定了事件处理方法 if (MarryEvent != null) { Console.WriteLine(msg); //触发事件 MarryEvent(this, new EventArgs()); } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyEventHandler { //朋友类 事件订阅者 public class Friend { //字段 public string _name; public Friend(string name) { _name = name; } //事件处理函数,该函数需要符合EventHandler委托定义 public void SendMessage(object s, EventArgs e) { //对事件做出处理 Console.WriteLine(this._name + "收到了,到时候准时参加"); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyEventHandler { class Program { static void Main(string[] args) { //初始化新郎官对象 BridegRoom br = new BridegRoom(); //实例化朋友对象 Friend f1 = new Friend("张三"); Friend f2 = new Friend("李四"); Friend f3 = new Friend("王五"); //使用“+=”来订阅事件 br.MarryEvent += new EventHandler(f1.SendMessage); br.MarryEvent += new EventHandler(f2.SendMessage); //发出通知,此时只有订阅了事件的对象才能收到通知 br.OnBirthdayComing("朋友们,我结婚了,到时候准时参加婚礼!"); Console.WriteLine("----------------------------------------"); //使用“-=”来取消事件订阅,此时李四将收不到通知 br.MarryEvent -= new EventHandler(f2.SendMessage); //使用“+=”来订阅事件,此时王五可以收到通知 br.MarryEvent += new EventHandler(f3.SendMessage); //发出通知 br.OnBirthdayComing("朋友们,我结婚了,到时候准时参加婚礼!"); Console.ReadKey(); } } }
EventHandler是.NET类库中预定义的委托类型,用于处理不包含事件数据的事件,如果想在事件中包含事件数据,可以通过派生EventArgs来实现,它的具体定义如下:
public delegate void EventHandler(object sender, EventArgs e);
从EventHandler委托的定义可以看出:
(1).该委托的返回类型为void,因此实例化委托类型的方法也需要满足这点;
(2).第一个参数sender负责保存对触发事件对象的引用,其类型为object;
(3).第二个参数e负责保存事件数据,EventArgs类也是.NET类库中定义的类,它不保存任何数据。
五.扩展EventArgs类
因为EventHandler只用于处理不包含事件数据的事件,如果我们想要在由这种方式定义的事件中包含事件数据,则可以通过派生EvnetArgs类来实现。下面通过扩展EvnetArgs类来使事件参数e带有事件数据。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyEventHandler { //自定义事件类,并使其带有事件数据 public class MarryEventArgs:EventArgs { public string _messsage; public MarryEventArgs(string msg) { _messsage = msg; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyEventHandler { //新郎官类,事件发布者角色 public class BridegRoom { //自定义委托类型,委托包含两个参数 public delegate void MarryHandler(object sender, MarryEventArgs e); //定义事件 public event MarryHandler MarryEvent; //发出事件 public void OnBirthdayComing(string msg) { //判断是否绑定了事件处理的方法 if(MarryEvent != null) { //触发事件 MarryEvent(this, new MarryEventArgs(msg)); } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyEventHandler { //朋友类 事件订阅者 public class Friend { //字段 public string _name; public Friend(string name) { _name = name; } //事件处理函数,该函数需要符合EventHandler委托定义 public void SendMessage(object s, MarryEventArgs e) { //输出通知信息 Console.WriteLine(e._messsage); //对事件做出处理 Console.WriteLine(this._name + "收到了,到时候准时参加"); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyEventHandler { class Program { static void Main(string[] args) { //初始化新郎官对象 BridegRoom br = new BridegRoom(); //实例化朋友对象 Friend f1 = new Friend("张三"); Friend f2 = new Friend("李四"); Friend f3 = new Friend("王五"); //使用“+=”来订阅事件 br.MarryEvent += new BridegRoom.MarryHandler(f1.SendMessage); br.MarryEvent += new BridegRoom.MarryHandler(f2.SendMessage); //发出通知,此时只有订阅了事件的对象才能收到通知 br.OnBirthdayComing("朋友们,我结婚了,到时候准时参加婚礼!"); Console.WriteLine("----------------------------------------"); //使用“-=”来取消事件订阅,此时李四将收不到通知 br.MarryEvent -= new BridegRoom.MarryHandler(f2.SendMessage); //使用“+=”来订阅事件,此时王五可以收到通知 br.MarryEvent += new BridegRoom.MarryHandler(f3.SendMessage); //发出通知 br.OnBirthdayComing("朋友们,我结婚了,到时候准时参加婚礼!"); Console.ReadKey(); } } }
以上代码通过自定义MarryEventArgs事件类扩展了EventArgs类,此时MarryEventArgs带有一个名为Message的事件参数;然后订阅对象的SendMessage方法中,通过e.Message的方式获得了事件数据,并把事件数据输出。