C#事件
事件我认为是C#其中一个难点,绕来绕去的,如果刚开始学习的话会有些困难。最近因为有相应的需求,并且看了网上诸多大佬的文章后,自己也有了一定的应用经验和了解,于是写出来分享一下。
我先打算用CLR via C#举得例子,就是电子邮件。我们工作或者日常生活中经常会用到电子邮件,当有某人往我们的邮箱发信息之后,会有相应的提示,我们看到了之后就肯定会打开邮箱去看邮件的内容是什么,这个就是事件的大体内容。事件可以用来处理很多问题,比如用户操作,如按键、点击、鼠标移动等等,或者是一些提示信息,如系统生成的通知。
事件有三个要素:事件拥有者、事件订阅者、事件处理方法
事件拥有者:也叫事件发布者,个人觉得用拥有者更方便理解,很显然,谁定义事件谁就是事件的拥有者。具体到代码中也就是哪个类中定义了的事件,那么这个类的实例就是事件的拥有者。
事件订阅者:一直在监听事件是否触发。
事件处理方法:事件触发后要执行的方法。当事件订阅者“发现”事件拥有者的事件被触发时,事件订阅者需要去执行的方法。一般来说,事件处理方法是定义在事件订阅者中。
除了上面三个,还有一个要素就是事件,里面包含着这个事件的内容,比如邮件信息、按键信息什么的
按照上面电子邮件的例子,电子邮箱这个系统即事件拥有者,用户即我们是事件订阅者,打开邮件进行查看这个操作就是事件处理方法。
之后用我自己的例子,我感觉这个更直观,就是按键交互。在很多应用中用户是需要用键盘与系统进行交互,所以按键事件很常见。
比如,当我们按下W键,在某个窗口就可以执行某个功能,这就可以用事件来解决。
实例程序:
//键盘事件 class KeyEvent : EventArgs { public string keycode { set; get; } public KeyEvent(string keycode) { this.keycode = keycode; } } //事件监听者 class KeyListener { private KeyInputManager km; public KeyListener(KeyInputManager km) { km.keyEventHandler += HandleEvent; } //事件处理函数 public void HandleEvent(Object sender, KeyEvent e) { Console.WriteLine("receive input " + e.keycode + " down"); switch (e.keycode) { case "W": Console.WriteLine("do W function"); break; } } } //事件拥有者 class KeyInputManager { public event EventHandler<KeyEvent> keyEventHandler; public void GetInput(string keycode) { keyEventHandler(this, new KeyEvent(keycode)); } } class Test { public static void Main() { KeyInputManager km = new KeyInputManager(); KeyListener ke = new KeyListener(km); //模拟按键 Thread.Sleep(2000); km.GetInput("K"); Thread.Sleep(2000); km.GetInput("W"); Thread.Sleep(2000); km.GetInput("E"); return; } }
KeyInputManager可以理解为键盘事件管理器,到时候全部按键的接受都可以给他,然后其他需要用到按键的窗口/模块可以通过事件的方式订阅键盘事件。这样就可以只通过一个管理器就可以有效管理很多窗口/模块。
细节的话,就是想要使用自定义事件,首先就需要定义一个EventArgs
//键盘事件 class KeyEvent : EventArgs { public string keycode { set; get; } public KeyEvent(string keycode) { this.keycode = keycode; } }
需要定义一个类,继承自EventArgs
然后事件拥有者需要的就是一个EventHandler<T>,T为之前自定义的事件类名,注意前面有个event
public event EventHandler<KeyEvent> keyEventHandler;
到时候所有的事件订阅者订阅的其实就是这个
还有事件处理函数,放在订阅者中,当订阅者监听到事件就会执行这个,注意参数,必须是这样,第一个参数是Object,e是EventHandler<T>中T同款
//事件处理函数 public void HandleEvent(Object sender, KeyEvent e) { Console.WriteLine("receive input " + e.keycode + " down"); switch (e.keycode) { case "W": Console.WriteLine("do W function"); break; } }
可以拥有多个事件处理函数,只需要在订阅的时候分好就行
km.keyEventHandler += HandleEvent;
这个就是订阅,代表keyEventHandler事件触发,我就去执行HandleEvent这个函数。如果想取消监听,就是-=(如同字符串拼接)
最后就是事件拥有者如何通知订阅者,如下
keyEventHandler(this, new KeyEvent(keycode));
this代表通知者是自己本身这个事件拥有者,第二个参数则是之前定义的Event
最终结果