本教程展示如何在 C# 中聲明事件、調用事件和掛接到事件。
C# 中的“事件”是當對象發生某些有趣的事情時,類向該類的客戶提供通知的一種方法。事件最常見的用途是用於圖形用戶界面;通常,表示界面中的控件的類具有一些事件,當用戶對控件進行某些操作(如單擊某個按鈕)時,將通知這些事件。
但是事件未必只用於圖形界面。事件為對象提供一種通常很有用的方法來發出信號表示狀態更改,這些狀態更改可能對該對象的客戶很有用。事件是創建類的重要構造塊,這些類可在大量的不同程序中重復使用。
使用委托來聲明事件。如果您尚未學習“委托教程”,您應先學習它,然後再繼續。請回憶委托對象封裝一個方法,以便可以匿名調用該方法。事件是類允許客戶為其提供方法(事件發生時應調用這些方法)的委托的一種方法。事件發生時,將調用其客戶提供給它的委托。
除聲明事件、調用事件和與事件掛鉤的示例以外,本教程還介紹下列主題:
下面的簡單示例展示一個 ListWithChangedEvent
類,該類類似於標准的 ArrayList
類,而且,每當列表內容更改時,該類均調用 Changed
事件。這樣一個通用用途的類可在大型程序中以多種方式使用。
例如,某字處理器可能包含打開的文檔的列表。每當該列表更改時,可能需要通知字處理器中的許多不同對象,以便能夠更新用戶界面。使用事件,維護文檔列表的代碼不需要知道需要通知誰,一旦文檔列表發生了更改,將自動調用該事件,正確通知每個需要通知的對象。使用事件提高了程序的模塊化程度。
// events1.cs using System; namespace MyCollections { using System.Collections; // A delegate type for hooking up change notifications. public delegate void ChangedEventHandler(object sender, EventArgs e); // A class that works just like ArrayList, but sends event // notifications whenever the list changes. public class ListWithChangedEvent: ArrayList { // An event that clients can use to be notified whenever the // elements of the list change. public event ChangedEventHandler Changed; // Invoke the Changed event; called whenever list changes protected virtual void OnChanged(EventArgs e) { if (Changed != null) Changed(this, e); } // Override some of the methods that can change the list; // invoke event after each public override int Add(object value) { int i = base.Add(value); OnChanged(EventArgs.Empty); return i; } public override void Clear() { base.Clear(); OnChanged(EventArgs.Empty); } public override object this[int index] { set { base[index] = value; OnChanged(EventArgs.Empty); } } } } namespace TestEvents { using MyCollections; class EventListener { private ListWithChangedEvent List; public EventListener(ListWithChangedEvent list) { List = list; // Add "ListChanged" to the Changed event on "List". List.Changed += new ChangedEventHandler(ListChanged); } // This will be called whenever the list changes. private void ListChanged(object sender, EventArgs e) { Console.WriteLine("This is called when the event fires."); } public void Detach() { // Detach the event and delete the list List.Changed -= new ChangedEventHandler(ListChanged); List = null; } } class Test { // Test the ListWithChangedEvent class. public static void Main() { // Create a new list. ListWithChangedEvent list = new ListWithChangedEvent(); // Create a class that listens to the list's change event. EventListener listener = new EventListener(list); // Add and remove items from the list. list.Add("item 1"); list.Clear(); listener.Detach(); } } }
This is called when the event fires. This is calle[1] [2] [3] 下一頁
d when the event fires.
public delegate void ChangedEventHandler(object sender, EventArgs e);
委托類型定義傳遞給處理該事件的方法的一組參數。多個事件可共享相同的委托類型,因此僅當尚未聲明任何合適的委托類型時才需要執行該步驟。
接下來,聲明事件本身。
public event ChangedEventHandler Changed;
聲明事件的方法與聲明委托類型的字段類似,只是關鍵字 event 在事件聲明前面,在修飾符後面。事件通常被聲明為公共事件,但允許任意可訪問修飾符。
if (Changed != null) Changed(this, e);
調用事件只能從聲明該事件的類內進行。
使用 += 和 -= 運算符完成此操作。為開始接收事件調用,客戶代碼先創建事件類型的委托,該委托引用應從事件調用的方法。然後它使用 += 將該委托寫到事件可能連接到的其他任何委托上。
// Add "ListChanged" to the Changed event on "List": List.Changed += new ChangedEventHandler(ListChanged);
當客戶代碼完成接收事件調用後,它將使用運算符 -= 從事件移除其委托。
// Detach the event and delete the list: List.Changed -= new ChangedEventHandler(ListChanged);
當創建可以從中派生的通用組件時,事件中有時出現似乎會成為問題的情況。由於事件只能從聲明它們的類中調用,因此派生類不能直接調用在基類內聲明的事件。雖然這有時符合需要,但通常使派生類能夠自由調用事件更合適。這通常通過為事件創建受保護的調用方法來實現。通過調用該調用方法,派生類便可以調用此事件。為獲得更大的靈活性,調用方法通常聲明為虛擬的,這允許派生類重寫調用方法。這使得派生類可以截獲基類正在調用的事件,有可能對這些事件執行它自己的處理。
在前面的示例中,這已用 OnChanged
方法實現。如果需要,派生類可調用或重寫該方法。
事件和字段之間的另一個差異是,事件可放在接口中,而字段不能。當實現接口時,實現類必須在實現接口的類中提供相應的事件。
盡管 C# 語言允許事件使用任意委托類型,但“.NET Framework”對於應為事件使用的委托類型有一些更嚴格的指南。如果打算將您的組件與“.NET Framework”一起使用,您可能希望遵守這些指南。
“.NET Framework”指南指示用於事件的委托類型應采用兩個參數:指示事件源的“對象源”參數和封裝事件的其他任何相關信息的“e”參數。“e”參數的類型應從 EventArgs 類派生。對於不使用其他任何信息的事件,“.NET Framework”已定義了一個適當的委托類型:EventHandler。
下面的示例是“示例 1”的修改版本,它遵守“.NET Framework”指南。該示例使用 EventHandler 委托類型。
// events2.cs using System; namespace MyCollections { using System.Collections; // A class that works just like ArrayList, but sends event // notifications whenever the list changes: public class ListWithChangedEvent: ArrayList { // An event that clients can use to be notified whenever the // elements of the list change: public event EventHandler Changed; // Invoke the Changed event; called whenever list changes: protected virtual void OnChanged(EventArgs e) { if (Changed != null) Changed(this,e); } // Override some of the methods that can change the list; // invoke event after each: public override int Add(object value) { int i = base.Add(value); OnChanged(EventArgs.Empty); return i; } public override void Clear() { base.Clear(); OnChanged(EventArgs.Empty); } public override object this[int index] { set { base[index] = value; OnChanged(EventArgs.Empty); } } } } namespace TestEvents { using MyCollections; class EventListener { private ListWithChangedEvent List; public EventListener(ListWithChangedEvent list) { List = list;上一頁 [1] [2] [3] 下一頁
// Add "ListChanged" to the Changed event on "List": List.Changed += new EventHandler(ListChanged); } // This will be called whenever the list changes: private void ListChanged(object sender, EventArgs e) { Console.WriteLine("This is called when the event fires."); } public void Detach() { // Detach the event and delete the list: List.Changed -= new EventHandler(ListChanged); List = null; } } class Test { // Test the ListWithChangedEvent class: public static void Main() { // Create a new list: ListWithChangedEvent list = new ListWithChangedEvent(); // Create a class that listens to the list's change event: EventListener listener = new EventListener(list); // Add and remove items from the list: list.Add("item 1"); list.Clear(); listener.Detach(); } } }
This is called when the event fires. This is called when the event fires.
上一頁 [1] [2] [3]