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