關於C#中的自訂事件產生:
目標:通過一個執行個體來按步驟說明C#中如何建立,引發,接收和取消事件。例子是一個表單程式,一個按鈕和一個標籤,點擊按鈕的時候就觸發一個事件得到目前時間,如果秒是後30秒就輸出一個Wasn't a right time!!
一,建立一個事件類型:
1,建立一個表單應用程式,添加一個button和lebelInfo,name分別為buttonRaise和labelInfo。
2,定義一個委託:
在表單類的聲明部分添加,
public delegate void ActionEventHandler(object sender, ActionCancelEventArgs e);
這裡我們聲明了一個新的委託類型ActionEventHandler,原因是我們後面要自己定製EventArg類(上面可見就是ActionCancelEventArgs類),方法名必須和委託匹配。
3,定義一個事件:
在上面代碼後面加上,
public static event ActionEventHandler Action;
我們定義了一個叫Action的事件,事件定義的文法要求指定與事件相關的委託。
4,建立自己定義的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對象,接收器希望取消或者停止事件的處理。我們為ActionCancelEventArgs添加一個message屬性,包含事件處理時候傳遞一個事件處理狀態的字串。
所有的基於EventArgs的類都負責在發送器和接收器之間來回傳送事件的資訊。大多情況下,EventArgs類中使用的資訊都被事件處理常式中的接收器對象(這裡後來的ActionCancelEventArgs ev)所使用。但是有時候,事件處理常式可以把資訊添加到EventArg類中,使之可以用於發送器。我們這裡就是這樣做的其實(接收器根據狀態把資訊傳給發送器中的message屬性了)。
二,引發事件:
1,通過一種動作來啟用Action事件(我們就用點擊按鈕buttonRaise):
先為buttonRaise按鈕添加一個點擊事件處理常式:
private void buttonRaise_Click(object sender, EventArgs e)
2,再在處理常式中用正確的參數呼叫事件:添加如下代碼,
ActionCancelEventArgs cancelEvent = new ActionCancelEventArgs();
OnAction(this, cancelEvent);
就是先建立一個新的事件數目據類型ActionCancelEventArgs,再把它當作參數傳遞給前面定義的那個Action事件的處理常式(引發事件是通過Action(this, cancelEvent)的,但是我們通過OnAction()來調用之)。這裡我們的Action事件就相當我們.Net中的Move,Click事件一樣的了,但是目前它還是空的,如果引發了這個事件就會產生一個Null 參考異常,所以我們如果在其他的類中把Action事件定義為基事件,則只要引發了Action就要定義相關的事件處理常式的。
3,我們定義一個叫OnAction的函數引發事件,(加上On是命名規範)
protected void OnAction(object sender, ActionCancelEventArgs e)
{
if (Action != null) //捕獲Null 參考錯誤
Action(sender, e);
}
如果派生一個包含該方法和事件的新類,就必須重寫OnAction方法,並且在重寫代碼中調用base.OnAction(),引發此事件。
三,接受事件,並且處理之:
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; }
}
}
}
其中關鍵代碼:
1,建構函式中聲明了Form1.Action事件的處理常式(註冊事件):
Form1.Action += new Form1.ActionEventHandler(Form1_Action);
注意這裡註冊的是Form1中定義的那個Action事件,不是其它地方定義的。
2,Action事件的處理常式(在前面Form1類中通過OnAction()引發的):
private void Form1_Action(object sender, ActionCancelEventArgs e)
其中的處理是通過調用DoAction函數來的。它返回一個bool值,並且將狀態資訊賦值給事件數目據類型ActionCancelEventArgs的參數的message成員。
3,完善Form1程式:
(1),類中要先建立成員private BusEntity busEntity;
(2),建構函式中初始化之:busEntity = new BusEntity();
(3),完善點擊按鈕的事件處理,引發並且處理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;
}
在補充說明:這裡建立了ActionCancelEventArgs對象,接著引發了Action事件,並且傳遞了建立的ActionCancelEventArgs對象cancelEvent。在調用OnAction方法,引發事件的時候,BusEntity對象中Action事件處理常式的代碼就會執行。如果還有其他對象註冊了事件,它們同樣會執行。記住:如果其他對象也處理了事件Action,它們也會看到同一個ActionCancelEventArgs對象。如果需要確定是哪個對象取消了事件,而且如果多個對象取消了事件,就要在ActionCancelEventArgs類中再包含某種基於列表的資料結構。
四,取消事件:
在與委託一起註冊的處理常式執行完之後,就可以查詢ActionCancelEventArgs對象,並且確定它是否被取消了。也就是下面代碼:
if (cancelEvent.Cancel)
labelInfo.Text = cancelEvent.Message;
else
labelInfo.Text = busEntity.TimeString;
總結:上面就是我個人通過《Professional C# 2005 with .Net 3.0》一書中的相關部分,總結出的如何利用事件和事件中基於EventArgs的對象,在應用程式中傳遞資訊的。程式樣本來源於此教程。
Copyright 2009 lcswr1987.CCBB. All Rights Reserved.
轉帖請標明出處:http://hi.baidu.com/lcswr/blog/item/9ba59063c08890670d33fa05.html