復古GB掌機“Analogue Pocket”將於12月13日開始發貨
事件我認為是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
最終結果