一、What's 事件
類別或物件可以透過事件向其他類別或物件通知發生的相關事情。發送(或引發)事件的類別稱為“發行者”,接收(或處理)事件的類別稱為“訂戶”(訂閱者)。
在典型的 C# Windows 窗體或 Web 應用程式中,可訂閱由按鈕和列錶框等控制項引發的事件。可以使用整合開發環境 (IDE) 來瀏覽控制項發佈的事件,並選擇想要處理的事件。 IDE 將自動新增空白事件處理程序方法和訂閱該事件的程式碼。
二、事件的屬性總結
發行者決定何時引發事件;訂戶決定對事件的回應。
一個事件可以有多個訂戶。訂戶可以處理來自多個發行者的多個事件。
沒有訂戶的事件永遠不會引發。
事件通常用於表示使用者操作,例如點擊按鈕或圖形使用者介面中的選單選項。
當事件具有多個訂戶時,引發該事件時預設會同步呼叫事件處理程序。
事件是基於 EventHandler 委託和 EventArgs 基類別。
三、事件的訂閱和取消
如果您想編寫引發事件時調用的自訂程式碼,則可以訂閱由其他類別發布的事件。例如,可以訂閱某個按鈕的 click 事件,以便讓應用程式在使用者點擊該按鈕時執行一些有用的操作。
1.用IDE 訂閱事件
圖3-1-1 新建一個WinForm 專案
圖3-1-2 由圖1雙擊時圖所建立的程式碼
3-1-3 除了圖2,在InitializeComponent 方法也自動增加了這行代碼
2.以編程方式訂閱事件
假設現在是一個新的WinForm 程序,我們通過手動的方式創建事件。在 InitializeComponent 方法下方輸入this.Load +=,然後會出現提示,這時我們按下“Tab 鍵”,
圖3-2-1
『 ,效果跟上一節的直接雙擊空白處創建的程式碼可以說是一致的,程式碼如下:
public partial class Form1 : Form { public Form1() { InitializeComponent(); this.Load += Form1_Load; } private void Form1_Load(object sender, EventArgs e) { throw new NotImplementedException(); } }
這次,我們直接採用lambda 方式完成事件的註冊:點擊空白處顯示滑鼠點擊時的座標。
public partial class Form1 : Form { public Form1() { InitializeComponent(); //this.Load += Form1_Load; //点击事件(lambda 方式创建) this.Click += (s, e) => { MessageBox.Show($"{((MouseEventArgs)e).Location}"); }; } private void Form1_Load(object sender, EventArgs e) { throw new NotImplementedException(); } }
【備註】內容涉及 $: (C# 6) 的語法,vs2015 以上才支援。 $"{msg}" 相當於 string.Format("{0}", msg), msg 指變數。
3.用匿名方法訂閱事件
public Form1() { InitializeComponent(); //this.Load += Form1_Load; //点击事件(lambda 方式创建) //this.Click += (s, e) => //{ // MessageBox.Show($"{((MouseEventArgs)e).Location}"); //}; //使用匿名方法创建事件 this.Click += delegate (object sender, EventArgs e) { var mouseEventArgs = (MouseEventArgs)e; var mouseLocation = mouseEventArgs.Location; MessageBox.Show($"X: {mouseLocation.X}, Y: {mouseLocation.Y}"); }; }
【注意】如果使用匿名函數訂閱事件,事件的取消訂閱過程將比較麻煩。在這種情況下若要取消訂閱,必須返回該事件的訂閱代碼,將該匿名方法儲存在委託變數中,然後將此委託加入該事件。一般來說,如果必須在後面的程式碼中取消訂閱某個事件,則建議您不要使用匿名函數訂閱此事件。
4.取消訂閱
要防止在引發事件時呼叫事件處理程序,請取消訂閱該事件。若要防止資源洩露,應在釋放訂戶物件之前取消訂閱事件。在取消訂閱事件之前,在發布對像中作為該事件的基礎的多路廣播委託會引用封裝了訂戶的事件處理程序的委託。只要發布物件保持該引用,垃圾回收功能就不會刪除訂戶物件。使用減法賦值運算子 (-=) 取消訂閱事件。
this.Load -= Form1_Load; //使用減法賦值運算子 (-=) 取消訂閱事件
戶則為備有事件【備者」所附註