Framework 類庫的事件程式設計

2021-04-23 05:12:57 字數 4875 閱讀 9588

**於http://study.qqcf.com,不過沒有作者,然後語言是vb的,但是應該相同的

eventhandler 委託

自定義的事件引數

引數化自定義事件

小結 本月的內容是專門介紹事件程式設計的系列專欄(共三期)的最後一期。在前兩期專欄中,我已經介紹了如何定義和引發事件(請參見 basic instincts:programming with events using .net 和 basic instincts:static event binding using withevents)。我還解釋了如何使用動態和靜態事件繫結來繫結事件處理程式。本月,我將通過一些在 microsoft .net framework 中處理較常用的事件處理例項來總結我對事件的介紹。

eventhandler 委託

當您使用 windows® 窗體或 asp.net 構建應用程式時,您會看到,在所遇到的事件中有相當大的比率是根據乙個名為 eventhandler 的通用委託型別定義的。eventhandler 型別存在於 system 命名空間中並具有以下定義:

delegate sub eventhandler(sender as object, e as eventargs)

委託型別 eventhandler 在它的呼叫簽名中定義了兩個引數。第乙個引數(名為 sender)是基於通用 object 型別的。sender 引數用於傳遞指向事件源物件的引用。例如,當 button 物件引發基於 eventhandler 委託型別的事件時,作為事件源的它將傳遞乙個對自身的引用。

由 eventhandler 定義的第二個引數名為 e,它是 eventargs 型別的物件。在許多情況下,事件源傳遞的引數值等於 eventargs.empty,這表明沒有額外引數資訊。如果事件源希望在 e 引數中傳遞額外的引數化資訊,則它應該傳遞乙個從 eventargs 類的派生類建立的物件。

圖 1 所示的示例在 windows 窗體應用程式中包含了兩個事件處理程式,它們使用靜態事件繫結來繫結。form 類的 load 事件和 button 類的 click 事件都是根據委託型別 eventhandler 定義的。

您還應該注意到,圖 1中的兩個事件處理程式方法的名稱和格式與 visual studio .net ide 為您生成的一致。例如,如果您在設計檢視中雙擊某個窗體或命令按鈕,visual studio .net 將自動建立類似的事件處理程式方法主幹。您需要做的僅僅是填充這些方法的實現,以便為您的事件處理程式賦予預期的行為。

您也許會注意到,visual studio .net ide 是使用 visual basic 6.0 要求的命名方案來生成處理程式方法的。然而,您應當記住的是,visual basic .net 中的靜態事件繫結並不真正與處理程式方法的名稱有關。與其相關的是 handles 子句。您可以隨意將處理程式方法重新命名為所需的任何名稱。

您可以重寫這兩個事件處理程式,以便它們使用動態事件繫結(而非靜態事件繫結)來繫結。例如,圖 2 中從 form 派生的類提供了與圖 1中從 form 派生的類完全相同的事件繫結行為。唯一的區別是,後者使用了動態事件繫結,並且不需要 withevents 關鍵字或 handles 關鍵字。在許多情況下,您將根據 eventhandler 委託型別來編寫處理程式方法的實現,而不是引用 sender 引數或 e 引數。例如,當您為從 form 派生的類的 load 事件編寫處理程式時,這些引數值並沒有實際的作用。sender 不會提供任何值,因為它只是傳遞 me 引用。e 引數傳遞 eventargs.empty:

sub form1_load(sender as object, e as eventargs) handles mybase.load

'*** these tests are always true

dim test1 as boolean = sender is me

dim test2 as boolean = e is eventargs.empty

end sub

您也許想知道,為什麼 load 事件的呼叫簽名沒有針對其需要進行更多自定義。畢竟,如果 load 事件根本不包含任何引數,情況將不會這麼令人困惑。要找到其他基於 eventhandler 委託型別的事件(並且其 sender 引數或 e 引數不傳遞任何值)的示例很容易。

請回答以下問題。如果該委託型別具有這樣的通用呼叫簽名,為什麼您會認為有這麼多事件根據 eventhandler 建模?.net framework 的設計者為什麼不根據具有適合其需要的呼叫簽名的自定義委託來為每個事件建模?如您所知,.net framework 開發中的乙個設計目標就是限制用於事件處理的委託的數量。以下幾條是更進一步的解釋。

最小化委託型別數量的第乙個目的是,為了更有效地利用應用程式所使用的記憶體。載入更多型別意味著占用更多記憶體。如果由 windows 窗體框架中的類定義的每個事件都基於乙個自定義委託,則每次執行 windows 窗體應用程式時都必須將上百個委託型別載入到記憶體中。windows 窗體框架可依賴很少的委託型別在 form 類和各種控制項類中定義上百個事件,從而提供更好的記憶體利用率。

最小化委託型別數量的第二個目的是,利用可插接式處理程式方法來增加實現多型性的可能。當您使用與 eventhandler 委託匹配的呼叫簽名來編寫處理程式方法時,可以將其繫結到大多數由窗體及其控制項引發的事件上。

讓我們來看一些編寫通用事件處理程式的示例。首先介紹這樣乙個示例:在這個示例中,可以通過將使用者輸入改為大寫來響應窗體中多個文字框的 textchanged 事件。沒必要為每個控制項都建立單獨的事件處理程式。相反,您可以只建立乙個事件處理程式,然後將其繫結到多個不同文字框的 textchanged 事件上(請參見圖 3)。

對於這個示例,首先應該注意的是,handles 子句並不僅限於乙個事件。您可以在 handles 關鍵字後面使用由逗號分隔的列表來包括任意數量的事件。在本示例中,使用了 textchangedhandler 方法來建立三個不同的事件處理程式。因此,當使用者更改這三個文字框中任意乙個的文字時,都將執行這個方法。

當執行 textchangedhandler 方法時,如何知道是哪個 textbox 物件引發該事件呢?這就是 sender 引數要解決的問題。請記住,sender 引數是根據通用型別 object 傳遞的。這意味著,在針對其程式設計之前,必須將它轉換成乙個更具體的型別。在前面的示例中,要訪問 sender 引數的 text 屬性,就必須將該引數轉換為 textbox。

如果您曾經使用 visual basic 的早期版本生成了基於窗體的應用程式,則您可能習慣於使用控制項陣列。在 visual basic 6.0 中使用控制項陣列的主要優勢在於,此功能使得建立乙個能夠響應由多個不同控制項引發的事件的處理程式方法成為可能。visual basic .net 不支援控制項陣列。然而,您無需過度緊張,因為您剛才已經看到,visual basic .net 提供了一種替代技術,可以將乙個處理程式方法繫結到多個不同的事件上。

.net framework 的事件體系結構還為您提供了控制項陣列無法實現的功能。例如,您可以建立乙個處理程式方法來響應由多個不同型別的控制項所引發的事件。圖 4 顯示了乙個處理程式方法示例,它繫結到三個不同控制項型別上的三個不同的事件上。

正如您所看到的,將處理程式方法繫結到事件的方案相當靈活。唯一的要求是,處理程式方法和它繫結到的事件應基於相同的委託型別。而 .net framework 中有相當多的事件都是基於 eventhandler 委託型別的,這使得編寫通用處理程式方法十分簡單。

當您編寫通用處理程式方法時,有時需要編寫**來執行條件操作,而這些操作只在事件源是某種特定型別的物件時才執行。例如,您的處理程式方法可以使用 typeof 運算子來檢查 sender 引數。這使得您的處理程式方法可以在事件源為 button 物件時執行一組操作,而在事件源為 checkbox 物件時執行另一組操作,如下所示:

sub generichandler1(sender as object, e as eventargs)

if (typeof sender is button) then

dim btn as button = ctype(sender, button)

'*** program against btn

elseif (typeof sender is checkbox) then

dim chk as checkbox = ctype(sender, checkbox)

'*** program against chk

end if

end sub

返回頁首

自定義的事件引數

基於 eventhandler 委託的事件通知通常不在 e 引數中傳送任何有意義的資訊。e 引數通常是無用的,因為它包含 eventargs.empty 值或 nothing 值。然而,.net framework 的設計者建立了乙個將引數化資訊從事件源傳遞到其事件處理程式的約定。此約定包括自定義事件引數類和自定義委託型別的建立。

由 form 類引發的滑鼠事件為應該如何使用此約定提供了乙個很好的示例。有關滑鼠位置和按下哪個滑鼠鍵的引數化資訊在乙個名為 mouseeventargs的類中建模。mouseeventargs 類包含了用於跟蹤滑鼠位置的 x 和 y 屬性,以及用於指示按下哪個滑鼠鍵的 button 屬性。請注意,按照約定,mouseeventargs 類必須從通用類 eventargs 繼承。

在事件通知中傳遞引數化資訊的約定需要乙個自定義委託來補充自定義事件引數類。因此,有乙個名為 mouseeventhandler 的委託用於補充 mouseeventargs 類。該處理程式委託的定義如下:

delegate sub mouseeventhandler(sender as object, e as mouseeventargs)

現在,假設您希望對乙個與滑鼠有關的事件(如 form 類的 mousedown 事件)作出響應。您可以編寫如圖 5 所示的處理程式方法。

請注意,e 引數在該處理程式方法的實現中非常有用。e 引數用於確定滑鼠位置以及按下哪個滑鼠鍵。所有這些引數化資訊都可以通過設計 mouseeventargs 類來實現。

iOS靜態庫 framework的製作

frameworke靜態庫的製作 1 先建立乙個新的xcode工程libtest,需要選擇下面這個模板 建立完成後是這個樣子的 建立完成後我們可以看到,工程本身自帶乙個libtest.h檔案和乙個info.plist檔案。2 我們建立乙個類printstring,新增乙個單純列印字串的簡單方法 3 ...

python類的程式設計 python中的類程式設計

1.python類中的幾個特殊函式 1 new 是建立類的物件的函式,相當於c 中建構函式。2 init 會在 new 之後被呼叫,用來初始化物件的。3 del 是物件將要被銷毀的時候被呼叫,用來將物件所占用的記憶體資源釋放給作業系統,相當於c 中的析構函式。2.python中類定義和使用 clas...

NanoPi NEO的Matrix庫硬體程式設計

nanopi neo的matrix庫硬體程式設計 1 準備工作 1 安裝matrix函式庫,類似於樹莓派的wiringpi函式庫,用來對nano pi的硬體進行操作 先安裝git sudo apt get install git 安裝好後看一下版本 git version 然後去github上拿到官...