Henry的VB.NET之旅(十四)—動態關聯事件與處理程式

latitude發表於2004-02-05

??? HenryVB.NET之旅(十四)動態關聯事件與處理程式<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

??????????????????????????????????? 韓睿

?

“要解釋新的事件處理程式的方法,我們需要先說幾個重要的問題。”大李開始嚴肅起來,我也只得挪動一下身子,表現出正襟危坐的架勢。

“我們首先討論一下事件是怎麼產生的。事件是物件傳送的訊息,以發訊號通知操作的發生。操作可能是由使用者互動,例如滑鼠單擊引起的,也可能是由某些其他的程式邏輯觸發的。引發事件的物件叫做事件傳送方(啊,聽到這,Henry突然明白了事件處理程式中的第一個參量為什麼叫Sender了,就是指事件傳送的那個物件呀。捕獲事件並對其作出響應的物件叫做事件接收方。在事件通訊中,事件傳送方類不知道哪個物件或方法將接收到它引發的事件。所需要的是在源和接收方之間存在一個媒介,或類似指標的機制。.NET 框架定義了一個特殊的型別Delegate,也就是委託,該型別提供函式指標的功能。”

“啊,我早就聽說過委託的,就是不知道它是什麼意思咧!”我做出期盼狀。

“委託就是可用於呼叫其他物件方法的物件。與其他的類不同,委託類具有一個簽名,並且它只能對與其簽名匹配的方法進行引用。”大李繼續說著。

““噢,委託也就是一個函式指標嘍。”我好象理解了一點。

“差不多,委託可以等效於一個型別安全函式指標或一個回撥。但不同於函式指標,Visual Basic.NET 委託是基於 System.Delegate 類的引用型別,它可以引用我們先前說過的共享方法(詳見《共享成員》一篇)和例項方法。”

“明白了一點。”我一邊點頭一邊說,“我們想要動態呼叫事件處理程式,是不是就要利用委託來宣告是哪個程式用於處理事件呀?”

大李驚異地看著我,露出了幾分讚許。

“委託是.NET中的一個重要的型別,我們以後還需要詳細討論。現在我們需要關注的就是如何來通過操作委託來實現將事件與事件處理程式動態聯絡起來。”大李接著就開始修改程式碼:

?

Module Module1

Public Class CHenry

??????? Public Event EventHR()??? ' 宣告一個事件

??????? Sub CauseSomeEvent()

??????????? RaiseEvent EventHR()?? ' 引發事件

??????? End Sub

??? End Class

?

??? Dim obj As New CHenry()

??? Sub Obj_EventHR()? '在Handles之後宣告事件

??????? MsgBox("事件處理器捕捉到了事件.")?? '處理事件.

??? End Sub

??? Sub Main()

??????? AddHandler obj.EventHR, AddressOf Obj_EventHR

??????? obj.CauseSomeEvent()?? '呼叫物件去引發事件

End Sub

End Module

?

“看到有什麼不同嗎?”大李轉過身來問我。

“主要有兩個不同,首先是obj的定義不再用WithEvents來標識了,因此事件處理程式obj_EventHR()也就不能通過Handles關鍵字來宣告事件,也就是說EventHR事件與事件處理程式沒有用WithEvent-Handles進行關聯;其次,是使用了AddHandleAddressof……”說到這,我也沒有詞了,只能語焉不詳。

“呵呵,我來幫你接著說。”大李拍了拍我的肩膀,接著說“先說Addressof吧,AddressOf 運算子建立的是一個指向指定的過程的過程委託。我們剛才說過委託相當於一個函式指標,那麼AddressOf就是委託的操作符,通過它能得到委託的引用。”

見到我稍稍明白了,大李又接著說:“光看AddHandle能夠將obj.EventHR事件與Obj_EventHR事件處理程式關聯起來的作法,你肯定不瞭解我所說的動態關聯好處在哪裡。因為我沒提到另一個方法RemoveHandler。它的使用方法和AddHandle是一樣的,比如:

RemoveHandler obj.EventHR, AddressOf Obj_EventHR

你看,AddHandler RemoveHandler 在一起就可以提供比 Handles 子句更大的靈活性,只要我們善於利用它們,就可以動態地新增、移除和更改與某事件關聯的事件處理程式。而且比 Handles 要強大的是,AddHandler 允許將多個事件處理程式與單個事件進行關聯。”

大李停了一停,接著說:“你要注意的一點就是AddressOf後面跟著的委託簽名應該與相應的事件資料類相一致,我們看一個例子。”

?

AddHandler TextBox.MouseDown,AddressOf TextBoxMouseDownHandler

‘錯誤的示例1:

Private Sub TextBoxMouseDownHandler( )

End Sub

錯誤的示例2

Private Sub TextBoxMouseDownHandler(ByVal sender As Object, ByVal e As EventArgs)

End Sub

‘正確的示例:

Private Sub TextBoxMouseDownHandler(ByVal sender As Object, ByVal e As MouseEventArgs)

End Sub

?

?“事件是一個文字框中的滑鼠按下事件,我們不用自帶的標準關聯事件處理方法,而用AddHandler來實現,那麼AddressOf之後相應的方法的引數宣告,應該與MouseDown事件對應的事件的委託MouseEventhandler具有相同的簽名,也就是引數宣告上要保持一致,一個object變數,一個System.Windows.Forms.MouseEventArgs變數。”

我到這一步才算明白了個大概,事件處理程式可以通過AddHandlerRemoveHandler方法在我們需要的時候動態地建立或斷開事件與事件處理程式的關聯關係。可是,對於大李剛說的“事件的委託MouseEventhandler”,我還是不太理解。

?

(未完待續)

---------------------------------------------------------------

宣告:本文版權與解釋權歸韓睿所有,如需轉載,請保留完整的內容及此宣告。

QQ: 18349592

E-Mail: henry7685@hotmail.com

???? 請訪問本人專欄:http://www.csdn.net/develop/author/netauthor/Latitude/

相關文章