Docs-.NET-.NET指南-事件:處理和引發事件
ylbtech-Docs-.NET-.NET指南-事件:處理和引發事件 |
1.返回頂部 |
處理和引發事件
.NET 中的事件基於委託模型。委託模型遵循觀察者設計模式,使訂閱者能夠向提供方註冊並接收相關通知。事件傳送方推送事件發生的通知,事件接收器接收該通知並定義對它的響應。本文介紹委託模型的主要元件、如何在應用程式中使用事件以及如何在你的程式碼中實現事件。
有關在 Windows 8.x Store 應用中處理事件的資訊,請參閱事件和路由事件概述。
事件
事件是由物件傳送的用於發出操作訊號的訊息。該操作可能是由使用者互動引起,例如單擊按鈕;也可能是由某些其他程式的邏輯導致,例如更改屬性值。引發事件的物件稱為“事件傳送方”。事件傳送方不知道哪個物件或方法將接收(處理)它引發的事件。事件通常是事件傳送方的成員,例如
若要定義一個事件,可以在事件類簽名中使用event
(在 C# 中)或Event
(在 Visual Basic 中)關鍵字,並指定事件的委託型別。委託在下一節中介紹。
通常,為了引發事件,您可以在 C# 中新增一個標記為protected
和virtual
或在 Visual Basic 中標記為Protected
和Overridable
的方法。將此方法命名為On
EventName;例如,OnDataReceived
。此方法應接受一個指定事件資料物件(EventArgsOn
EventName方法,以確保註冊的委託接收事件。
下面的示例顯示如何宣告名為ThresholdReached
事件。該事件與EventHandler委託相關聯並且由OnThresholdReached
方法引發。
class Counter
{
public event EventHandler ThresholdReached;
protected virtual void OnThresholdReached(EventArgs e)
{
EventHandler handler = ThresholdReached;
handler?.Invoke(this, e);
}
// provide remaining implementation for the class
}
委託
委託是一種儲存對方法的引用的型別。委託是通過顯示所引用方法的返回型別和引數的簽名來宣告的,並可以僅儲存與其簽名匹配的方法的引用。因此,委託等同於型別安全函式指標或回叫。委託宣告足以定義委託類。
委託在 .NET 中有許多用途。在事件上下文中,委託是事件源和處理事件的程式碼之間的媒介(或類似指標的機制)。如上一節的例子所示,可以通過在事件宣告中包括委託型別來將委託和事件相關聯。有關委託的詳細資訊,請參閱Delegate類。
.NET 提供了EventHandler和EventHandler<TEventArgs>委託來支援大部分事件場景。使用EventHandler委託處理不包含事件資料的所有事件。使用EventHandler<TEventArgs>委託處理包含事件相關資料的事件。這些委託沒有返回型別值,並且接受兩個引數(事件源的物件和事件資料的物件)。
委託是多播,這意味著它們可以儲存對多個事件處理方法的引用。有關詳細資訊,請參閱Delegate參考頁。委託提供了事件處理中的靈活性和精確控制。委託人通過維護事件的已註冊事件處理程式列表來充當引發事件的類的事件排程程式。
在EventHandler和EventHandler<TEventArgs>委託不可用的場景下,您可以定義一個委託。要求你定義委託的場景非常少見的,例如,當你必須處理無法識別泛型的程式碼時。在宣告中使用delegate
(在 C# 中)和Delegate
(在 Visual Basic 中)關鍵字標記委託。下面的示例說明如何宣告ThresholdReachedEventHandler
委託。
public delegate void ThresholdReachedEventHandler(object sender, ThresholdReachedEventArgs e);
事件資料
與事件相關的資料可以通過事件資料類提供。.NET 提供了許多事件資料類,使用者可以在自己的應用程式中使用它們。例如,SerialDataReceivedEventArgs類是SerialPort.DataReceived事件的事件資料類。.NET 遵循所有事件資料類以EventArgs
結尾的命名模式。您通過檢視事件的委託來確定哪個事件資料類與事件相關聯。例如,SerialDataReceivedEventHandler委託包含SerialDataReceivedEventArgs類作為它的一個引數。
EventArgs類是所有事件資料類的基型別。當一個事件沒有任何與其相關聯的資料時,您也會用到EventArgs類。當您建立一個事件僅用來通知其他類出問題了,不需要傳遞任何資料時,請包括EventArgs類作為委託中的第二個引數。當沒有資料提供時,您可以傳遞EventArgs.Empty值。EventHandler委託包括EventArgs類作為一個引數。
當您想建立一個自定義的事件資料類時,請建立一個派生自EventArgs的類,然後提供所需的所有成員,來傳遞與該事件相關的資料。通常,應使用與 .NET 相同的命名模式,並且事件資料類名稱應以EventArgs
結尾。
下面的示例演示了一個名為ThresholdReachedEventArgs
的事件資料類。它包含特定於引發事件的屬性。
public class ThresholdReachedEventArgs : EventArgs
{
public int Threshold { get; set; }
public DateTime TimeReached { get; set; }
}
事件處理程式
若要響應事件,您需要在事件接收器中定義一個事件處理程式方法。此方法必須與您正處理的事件的委託簽名匹配。在事件處理程式中,當事件引發時會執行所需操作,例如在使用者單擊按鈕之後收集使用者輸入。若當事件發生時收到通知,您的事件處理程式方法必須訂閱該事件。
下面的示例演示與c_ThresholdReached
委託的簽名匹配的EventHandler事件處理程式方法。該方法訂閱ThresholdReached
事件。
class Program
{
static void Main()
{
var c = new Counter();
c.ThresholdReached += c_ThresholdReached;
// provide remaining implementation for the class
}
static void c_ThresholdReached(object sender, EventArgs e)
{
Console.WriteLine("The threshold was reached.");
}
}
靜態和動態事件處理程式
藉助 .NET,訂閱者可以進行靜態或動態註冊以獲得事件通知。對於其事件由靜態事件處理程式進行處理的類,靜態事件處理程式對其整個生命週期有效。通常為響應某些條件程式邏輯,會在程式執行期間顯式啟用和停用動態事件處理程式。例如,如果僅在特定條件下需要事件通知,或如果應用程式提供多個事件處理程式且由執行時條件定義要使用的適當事件處理程式,則可以使用動態事件處理程式。上一節中的示例演示如何動態新增事件處理程式。有關詳細資訊,請檢視 Visual Basic 中的事件和 C# 中的事件。
引發多個事件
如果您的類引發多個事件,編譯器會為每一個事件委託例項生成一個欄位。如果事件數量很大,則可能無法接受按一個委託計算一個欄位的儲存成本。對於這些情況,.NET 提供一個事件屬性,可以將其與選擇的另一資料結構一起用於儲存事件委託。
事件屬性由事件宣告和事件訪問器組成。事件訪問器是您定義的方法,用來從儲存資料結構新增和移除事件委託例項。請注意,事件屬性要比事件欄位慢,這是因為必須先檢索每個事件委託,然後才能呼叫它。需在記憶體和速度之間進行權衡。如果類定義許多不常引發的事件,那麼需要實現事件屬性。有關詳細資訊,請參閱如何:使用事件屬性處理多個事件。
相關主題
Title | 描述 |
---|---|
如何:丟擲和使用事件 | 包含引發和使用事件的示例。 |
如何:使用事件屬性處理多個事件 | 演示如何使用事件屬性處理多個事件。 |
觀察程式設計模式 | 描述允許訂閱者向提供方註冊和接收通知的設計模式。 |
如何:在 Web 窗體應用程式中使用事件 | 演示如何處理 Web 窗體控制元件引發的事件。 |
請參閱
- EventHandler
- EventHandler<TEventArgs>
- EventArgs
- Delegate
- 事件 (Visual Basic)
- 事件(C# 程式設計指南)
- 事件和路由事件概述(UWP 應用)
2.返回頂部 |
3.返回頂部 |
4.返回頂部 |
5.返回頂部 |
6.返回頂部 |
作者:ylbtech 出處:http://ylbtech.cnblogs.com/ 本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利。 |