首先介紹一個為什么要在事件中引入委托這個概念:
事件是對象發送的消息,以發信號通知操作的發生。操作可能是由用戶交互(例如鼠標單擊)引起的,也可能是由某些其他的程序邏輯觸發的。引發事件的對象稱為事件發送方。捕獲事件并對其作出響應的對象叫做事件接收方。
在事件通信中,事件發送方類不知道哪個對象或方法將接收到(處理)它引發的事件。所需要的是在源和接收方之間存在一個媒介(或類似指針的機制)。.NET Framework 定義了一個特殊的類型(Delegate),該類型提供函數指針的功能。
原理簡介:
在C#中,一個類可以有域(Fields)、屬性(Properties)、方法(Methods)、索引(Indexs)、事件(Events),以及委托(delegate)等成員,其中事件(Events)成員就是用來聲明一個類事件的。在類中聲明一個事件成員一般采用如下的語法形式:
Public event 代理名 事件名
如在某個類中申明一個MyClick事件成員,其語法如下:
Public event DelegateName(自定義的一個委托) MyClick;
在C#中,增加了一個新的數據類型delegate(代表)來解決事件處理問題。代表數據類型非常類似于C語言中的指針,其與指針不同的是,其是代碼是安全的,可管理的。這里是DelegateName可以是系統已經提供的代理EventHandler,也可以是自己預先定義好的委托,委托的定義如下:
Public delegate [返回值] delegatename(委托的名字)(參數列表……..)
(它可以放在類外面,也可以放到類中,只要能在代碼中訪問到即可)
這里注意:如果是這個委托為事件而申明的,這里的返回值的類型就只能是void類型的,否則就要出現問題.
在C#中,通過使用delegate,你可以通過“+=”(加等于)操作符非常容易地為.Net對象中的一個事件添加一個甚至多個響應方法;還可以通過非常簡單的“-=”(減等于)操作符取消這些響應方法。如下面為temp按鈕添加Click事件的語句:
在上面聲明事件的語句中,Eventhandler是一個delegate(代表)類型,其在.Net類庫中如下聲明的:
public delegate void EventHandler(object sender,EventArgs e);
這樣,所有形如:void 函婁名(object 參數名,EventArgs 參數名); 的函數都可以作為Control類的Click事件響應方法了。如下面所定義的一個事件響應方法:
private void button1_Click(object sender, System.EventArgs e)
由于是通過delegate(代表類型)來處理事件,因此,可能通過累加使一個事件具有多個響應方法;與此同時,還可以使一個方法作為多個事件的響應方法。(注意:在C#語言類中的event成員后面只能出現“+=”與“-=”兩個表示添加與取消事件響應函數的操作符。)
不管是ASP.Net還是一般的Windows Forms 編程,在C#中,基本上我們遇到的事件響應方法都是說明成如下的形式:
private void button1_Click(object sender, System.EventArgs e)
(參考其他資料)
一個事件響應方法的存取權限、返回值類型、參數及類型甚至方法名稱等是否都必須固定不變呢?答案是:不是!
一般情況下,事件的響應方法中都有兩個參數,其中一個代表引發事件的對象即sender,由于引發事件的對象不可預知的,因此我們把其聲明成為object類型,所有的對象都適用。第二個參數代表引發事件的具體信息,各種類型的事件中可能不同,這要根據類中事件成員的說明決定。
我們知道,事件是通過delegate(代表) 來處理的。假設將要表示事件的代表說明成如下形式:
delegate int MyEventHandler(object sender, ToolBarButtonClickEventArgs e);
則當涉及上面的事件響應函數聲明時,就須要聲明成如下的形式:
private int MyTest(object sender,ToolBarButtonClickEventArgs e)
{
}
在給對象添加事件響應方法時就可以用如下的代碼實現:
Control.Event+=new MyEventHandler(MyTest);
下面是我根據對委托的理解,自己編寫的代碼,
注意目的是為了深入理解事件是怎樣和委托結合的。我的想法是這樣的:既然microsft已經為button按鈕寫了onclick事件了(不傳遞任何參數進入事件),我就打算重新添加一個MyClick事件,當 按鈕的onclick事件發生的時候,我就重寫默認的onclick事件,執行自己添加的MyClick事件,并傳遞參數進入事件(MyClick)中進行處理。
首先添加一個自定義的按鈕MyButton,它繼承于System.Window.Forms.Button類的.代碼如下:
namespace ExampleAddEventForm
{
public delegate void MyDelegate(object sender,object myevenargs); //這里把申明委托放到了類外,其實放到類中也一樣,只是引用地址不同而已。
public class MyButton:System.Windows.Forms.Button
{
protected override void OnClick(EventArgs e)
{//重寫默認的onclick方法,觸發自己的事件
TriggerEvent();
}
public event MyDelegate MyDelegateEvent; //申明一個事件
public void TriggerEvent()
{
if (MyDelegateEvent != null)
{
MyEvenArgs myevenargs = new MyEvenArgs();
myevenargs.FirstName = "cc";
myevenargs.LastName = "changchang";
MyDelegateEvent(this,myevenargs);
}
}
}
}
上面的MyEvenArgs類是我自定義的類,它繼承與系統提供的System.EvenArgs類注意目的是為了傳入參數進入方法。
Namespace ExampleAddEventForm
{
class MyEvenArgs:System.EventArgs
{
private string firstname;
public string FirstName
{
get { return firstname; }
set { firstname = value; }
}
private string lastname;
public string LastName
{
get { return lastname; }
set { lastname = value; }
}
}
}
到現在為止,我們已經實現了自己的按鈕(自定義了事件和委托,并重寫了microsft為我們提供的onclick事件,執行我們的OnClick事件)和Onclick事件中需要的傳遞參數的MyEvenArgs類
下面就把我們寫的MyButton按鈕放到頁面上(不是拖放到頁面上,這是不可能的),我們至少都要在InitializeComponent方法中加載到頁面上
private MyButton mybutton
private void InitializeComponent()
{
this.mybutton = new MyButton();
this.SuspendLayout();
this.mybutton.Location = new System.Drawing.Point(71, 99);
this.mybutton.Name = "mybutton";
this.mybutton.Size = new System.Drawing.Size(150, 23);
this.mybutton.TabIndex = 0;
this.mybutton.Text = "Override Button";
this.mybutton.UseVisualStyleBackColor = true;
this.mybutton.MyDelegateEvent += new.MyDelegate(this.MyButton_Click);
this.Controls.Add(mybutton);
}
這時回到設計界面提示錯誤(這是正常的)(沒有刷新)。從這里可以看到
mybutton.MyDelegateEvent += new MyDelegate(MyButton_Click);
這句話就是注冊事件,用自定義button中事件執行MyButton_Click函數方法,其實這就是事件處理程序。
返回到后臺代碼的如下:(這里只是簡單的提示有用的消息) public void MyButton_Click(object sender, MyEvenArgs message)
{
MessageBox.Show(message.FirstName+message.LastName); //這個就是傳遞個事件處理程序中的參數
MessageBox.Show("this is a custom button's click!");
}
現在代碼就結束了,運行程序就彈出“this is a custom button’s click”的提示.
轉載于:https://www.cnblogs.com/horse/archive/2010/02/20/1669629.html