C#自定義事件是如何生成的
目標:通過一個實例來按步驟說明C#自定義事件如何創(chuàng)建,引發(fā),接收和取消。例子是一個窗體程序,一個按鈕和一個標簽,點擊按鈕的時候就觸發(fā)一個事件得到當前時間,如果秒是后30秒就輸出一個Wasn't a right time!!
創(chuàng)建一個事件類型:
1.新建一個窗體應(yīng)用程序,添加一個button和lebelInfo,name分別為buttonRaise和labelInfo。
2.定義一個委托:
在窗體類的聲明部分添加
- public delegate void ActionEventHandler(object sender, ActionCancelEventArgs e);
這里我們聲明了一個新的委托類型ActionEventHandler,原因是我們后面要自己定制EventArg類(上面可見就是ActionCancelEventArgs類),方法名必須和委托匹配。
3.定義一個C#自定義事件:
在上面代碼后面加上,
- public static event ActionEventHandler Action;
我們定義了一個叫Action的事件,事件定義的語法要求指定與事件相關(guān)的委托。
4.創(chuàng)建自己定義的EventArg類:
在程序中定義一個類代碼如下:
- namespace WindowsApplication1
- {
- public class ActionCancelEventArgs : System.ComponentModel.CancelEventArgs
- {
- string message = String.Empty;
- public ActionCancelEventArgs() : base() { }
- public ActionCancelEventArgs(bool cancel) : base(cancel) { }
- public ActionCancelEventArgs(bool cancel, string message)
- : base(cancel)
- {
- this.message = message;
- }
- public string Message
- {
- get { return message; }
- set { message = value; }
- }
- }
- }
這個新類ActionCancelEventArgs實際上派生于CancelEventArgs,而CancelEventArgs派生于EventArgs。CancelEventArgs添加了Cancel屬性,是一個bool類型,它通知sender對象,接收器希望取消或者停止事件的處理。我們?yōu)锳ctionCancelEventArgs添加一個message屬性,包含事件處理時候傳遞一個事件處理狀態(tài)的字符串。
所有的基于EventArgs的類都負責在發(fā)送器和接收器之間來回傳送事件的信息。大多情況下,EventArgs類中使用的信息都被事件處理程序中的接收器對象(這里后來的ActionCancelEventArgs ev)所使用。但是有時候,事件處理程序可以把信息添加到EventArg類中,使之可以用于發(fā)送器。我們這里就是這樣做的其實(接收器根據(jù)狀態(tài)把信息傳給發(fā)送器中的message屬性了)。
引發(fā)事件:
1.通過一種動作來激活A(yù)ction事件(我們就用點擊按鈕buttonRaise):
先為buttonRaise按鈕添加一個點擊事件處理程序:
- private void buttonRaise_Click(object sender, EventArgs e)
2.再在處理程序中用正確的參數(shù)調(diào)用事件:添加如下代碼,
- ActionCancelEventArgs cancelEvent = new ActionCancelEventArgs();
- OnAction(this, cancelEvent);
就是先創(chuàng)建一個新的事件數(shù)據(jù)類型ActionCancelEventArgs,再把它當作參數(shù)傳遞給前面定義的那個Action事件的處理程序(引發(fā)事件是通過Action(this, cancelEvent)的,但是我們通過OnAction()來調(diào)用之)。這里我們的Action事件就相當我們.Net中的Move,Click事件一樣的了,但是目前它還是空的,如果引發(fā)了這個事件就會產(chǎn)生一個空引用異常,所以我們?nèi)绻谄渌念愔邪袮ction事件定義為基事件,則只要引發(fā)了Action就要定義相關(guān)的事件處理程序的。
3.我們定義一個叫OnAction的函數(shù)引發(fā)事件,(加上On是命名約定)
- protected void OnAction(object sender, ActionCancelEventArgs e)
- {
- if (Action != null) //捕獲空引用錯誤
- Action(sender, e);
- }
如果派生一個包含該方法和事件的新類,就必須重寫OnAction方法,并且在重寫代碼中調(diào)用base.OnAction(),引發(fā)此事件。
接受事件,并且處理之:
1.下面就是定義一個新類BusEntity了:
- namespace WindowsApplication1
- {
- public class BusEntity
- {
- string time = String.Empty;
- public BusEntity()
- {
- Form1.Action += new Form1.ActionEventHandler(Form1_Action);
- }
- private void Form1_Action(object sender, ActionCancelEventArgs e)
- {
- e.Cancel = !DoActions();
- if (e.Cancel)
- e.Message = "Wasn't the right time.";
- }
- private bool DoActions()
- {
- bool retVal = false;
- DateTime tm = DateTime.Now;
- if (tm.Second < 30)
- {
- time = "The time is " + DateTime.Now.ToLongTimeString();
- retVal = true;
- }
- else
- time = "";
- return retVal;
- }
- public string TimeString
- {
- get { return time; }
- }
- }
- }
其中關(guān)鍵代碼:
1.構(gòu)造函數(shù)中聲明了Form1.Action事件的處理程序(注冊事件):
- Form1.Action += new Form1.ActionEventHandler(Form1_Action);
注意這里注冊的是Form1中定義的那個Action事件,不是其它地方定義的。
2.Action事件的處理程序(在前面Form1類中通過OnAction()引發(fā)的):
- private void Form1_Action(object sender, ActionCancelEventArgs e)
其中的處理是通過調(diào)用DoAction函數(shù)來的。它返回一個bool值,并且將狀態(tài)信息賦值給事件數(shù)據(jù)類型ActionCancelEventArgs的參數(shù)的message成員。
3.完善Form1程序:
(1)類中要先新建成員private BusEntity busEntity;
(2)構(gòu)造函數(shù)中初始化之:busEntity = new BusEntity();
(3)完善點擊按鈕的事件處理,引發(fā)并且處理Action事件:
- private void buttonRaise_Click(object sender, EventArgs e)
- {
- ActionCancelEventArgs cancelEvent = new ActionCancelEventArgs();
- OnAction(this, cancelEvent);
- if (cancelEvent.Cancel)
- labelInfo.Text = cancelEvent.Message;
- else
- labelInfo.Text = busEntity.TimeString;
- }
在補充說明:這里創(chuàng)建了ActionCancelEventArgs對象,接著引發(fā)了Action事件,并且傳遞了新建的ActionCancelEventArgs對象cancelEvent。在調(diào)用OnAction方法,引發(fā)事件的時候,BusEntity對象中Action事件處理程序的代碼就會執(zhí)行。如果還有其他對象注冊了事件,它們同樣會執(zhí)行。記?。喝绻渌麑ο笠蔡幚砹耸录嗀ction,它們也會看到同一個ActionCancelEventArgs對象。如果需要確定是哪個對象取消了事件,而且如果多個對象取消了事件,就要在ActionCancelEventArgs類中再包含某種基于列表的數(shù)據(jù)結(jié)構(gòu)。
取消事件:
在與委托一起注冊的處理程序執(zhí)行完之后,就可以查詢ActionCancelEventArgs對象,并且確定它是否被取消了。也就是下面代碼:
- if (cancelEvent.Cancel)
- labelInfo.Text = cancelEvent.Message;
- else
- labelInfo.Text = busEntity.TimeString;
總結(jié):上面就是我個人通過《Professional C# 2005 with .Net 3.0》一書中的相關(guān)部分,總結(jié)出的如何利用事件和事件中基于EventArgs的對象,在應(yīng)用程序中傳遞信息的,生成C#自定義事件。程序示例來源于此教程。
【編輯推薦】