this.button1.Click += new System.EventHandler(this.button1_Click);

weixin_34162629發表於2016-06-22

 

在這個程式裡,這裡的修改是為了更好理解,當然這種寫法是語法錯誤的。

下面我們對其進行分析:

首先,觀察“=”右面的表示式。

new System.EventHandler(this.button1_Click);

通過6.1.1一節中的說明,大家可以發現,這段程式碼實際上是建立了一個委託型別的例項,並讓該委託指向了this.button1_Click方法。也就是說,在程式執行的“某一時刻”,系統會通過這個委託例項間接的呼叫this.button1_Click方法。

然後,我們再來觀察“=”左面的表達示。在C風格的語言中“=”是賦值表示式,也就是說,“=”兩側表示式的資料型別應該是一樣的。因此,既然“=”右側的表示式是一個委託型別(System.EventHandler)的例項,那麼this.button1.Click也應該是一個委託型別(System.EventHandler)。

通過上面的說明,我們得到一個資訊,前面這段事件註冊程式碼,是讓this.button1.Click和System.EventHandler(this.button1_Click)指向了同一段記憶體空間,簡單來講,就是讓this.button1.Click指向了this.button1_Click方法,呼叫了this.button1.Click,就相當於呼叫了this.button1_Click方法。因此,我們說,當this.button1的Click事件發生之後,方法this.button1_Click就會被呼叫。

在程式執行的時候,系統會自己檢測this.button1是否被點選了,如果被點選了,就在button1的內部呼叫button1.Click,這時,Windows視窗中的button1_Click方法就會被執行。

當然,事件註冊程式碼完全可以手寫。因為,除了控制元件中事件註冊程式碼是自動生成以外,其他類中的事件註冊都是手寫的。手工註冊事件的方法如下:

首先,可以在事件發生之前的任何程式碼中新增事件(通常是在視窗的構造方法中),下面我們來手工註冊button1的MouseMove事件,如下圖所示:

當我們寫完“=”時,會出現一個提示“Press TAB to insert”,這時,我們只需要按2下“TAB”鍵,事件的註冊以及用於回撥的方法,就會自己新增到程式碼視窗裡,如下圖所示:

自動生成的程式碼是將this.button1的MouseMove事件指向了button1_MouseMove方法。這樣手寫的程式碼和IDE自動生成的程式碼是完全一樣的。

當然,作為控制元件的事件,我們完全可以自動生成,如果想自動生成button1的其他事件,只需要檢視button1的屬性視窗,並點選“”按鈕,就會出現該控制元件的事件列表,如下圖所示:

然後雙擊你想要的事件,程式碼就會自動生成了。

在前的面程式碼中為了更好理解事件註冊,我們曾將

this.button1.Click += new System.EventHandler(this.button1_Click);

修改為

this.button1.Click = new System.EventHandler(this.button1_Click);

我們會發現,無論是自己寫的事件註冊程式碼,還是自動生成的程式碼,都是使用“+=”來實現的,實際上,作為事件註冊的程式碼,我們僅僅能夠使用“+=”來實現註冊,簡單的使用“=”是語法錯誤的!!!

“+=”操作符在C風格語言中是常用的操作符,比如

int i=0;

i+=1;

等同於

int i=0;

i=i+1;

因此,

this.button1.Click += new System.EventHandler(this.button1_Click);

在原則上等同於

this.button1.Click = this.button1.Click +

new System.EventHandler(this.button1_Click);

用自然語言來描述上面的程式碼就是“一個委託=這個委託本身+另外一個委託”。那麼委託相加意味著什麼呢?

在6.1.3一節中,我們討論過MultiDelegate(多播委託),而事件本身也是委託,並且所有委託都是System.MultiDelegate類的派生類,在6.1.3中,我們曾經演示過,多個委託型別例項相加,就是將這些委託例項存放在一個多播委託的呼叫鏈中,當呼叫多播委託時,該多播委託的呼叫鏈中的所有委託都會順序的被呼叫。

利用多播委託的原理,我們可以將多個方法註冊給一個事件,如下所示:

this.button1.Click +=new System.EventHandler(this.button1_Click);

this.button1.Click +=new System.EventHandler(this.button1_Click1);

this.button1.Click +=new System.EventHandler(this.button1_Click2);

上面的程式碼,就將三個方法註冊到了button1的Click事件中,當button1的Click事件觸發之後,方法button1_Click,button1_Click1,button1_Click2將會被順序呼叫。這樣作的好處是,我們可以將多個功能以及邏輯完全獨立的操作放在不同的方法中,當事件發生之後,這些方法將會順序的被呼叫,以實現我的需要的級聯操作。

6.2.3 控制元件中事件的回撥方法

說完了事件的註冊,下面我們來談一下事件的回撥方法。首先,我們還要再一次回顧事件註冊的程式碼:

this.button1.Click +=new System.EventHandler(this.button1_Click);

上面程式碼中,使用“new System.EventHandler(this.button1_Click)”將一個System.EventHandler委託型別的例項指向了this.button1_Click方法。通過6.1.1一節中所談到的內容,我們知道,如果想讓一個委託指向一個方法,那麼該委託以及所被指向的方法一定要具備相同的簽名(Signature,具備相同的引數列表,相同的返回值)。因此,System.EventHandler型別和this.button1_Click方法具備相同的簽名,下面,我們來看一下System.EventHandler委託的簽名是什麼樣的:

public delegate void EventHandler(

              Object sender,

              EventArgs e

)

System.EventHandler的簽名是:返回值為void;有兩個引數,Object sender, EventArgs e。因此button1_Click方法也具備相同形式,程式碼如下:

private void button1_Click(object sender, EventArgs e)

{

}

實際上,我們所能夠看到的事件回撥方法的簽名基本上都著不多,只不過第二個引數略有區別,下面,我們對該方法的引數進行說明。

Ø         Object sender

從該引數的命名上,可以看出其作用,sender(傳送者)的意思是:誰觸發的這個事件,那麼sender就是誰,由於所有的型別在理論上講都可以包括事件,因此sender的型別被定義成Object型別,當多個事件同時指向一個事件回撥方法的時候,通過該引數可以區分出是哪一個類觸發的事件,以便做出不同的處理,此時,需要對引數sender作出型別轉化。

l         案例操作020603:多個事件指向同一個回撥方法

首先,新增三個Button,一個TextBox

介面如下:

然後,在主視窗中新增一個方法ButtonClick,這三個按鈕的Click事件將呼叫該方法。

程式碼如下:

protected void ButtonClick(object sender, EventArgs e)

{

     Button bt = sender as Button;

     this.textBox1.Text ="我是:"+ bt.Text;

}

上面程式碼中,為了知道點選的是哪個按鈕,我們將sender轉化成了Button型別。

下面來指定這三個按鈕的Click事件回撥方法

首先,切換到button1的屬性視窗(F4),點選“”按鈕,找到“Click”事件,並設定所呼叫的方法名為ButtonClick ,如下圖所示。

然後,以相同的方法設定button2,button3的Click事件,並它們都指向ButtonClick方法。

最後,執行程式,下面是執行情況:

點選button1:

相關文章