程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C# 程序員參考--事件教學文章

C# 程序員參考--事件教學文章

編輯:C#入門知識

本教程展示如何在 C# 中聲明事件、調用事件和掛接到事件。

教程

C# 中的“事件”是當對象發生某些有趣的事情時,類向該類的客戶提供通知的一種方法。事件最常見的用途是用於圖形用戶界面;通常,表示界面中的控件的類具有一些事件,當用戶對控件進行某些操作(如單擊某個按鈕)時,將通知這些事件。

但是事件未必只用於圖形界面。事件為對象提供一種通常很有用的方法來發出信號表示狀態更改,這些狀態更改可能對該對象的客戶很有用。事件是創建類的重要構造塊,這些類可在大量的不同程序中重復使用。

使用委托來聲明事件。如果您尚未學習“委托教程”,您應先學習它,然後再繼續。請回憶委托對象封裝一個方法,以便可以匿名調用該方法。事件是類允許客戶為其提供方法(事件發生時應調用這些方法)的委托的一種方法。事件發生時,將調用其客戶提供給它的委托。

除聲明事件、調用事件和與事件掛鉤的示例以外,本教程還介紹下列主題:

  • 事件和繼承
  • 接口中的事件
  • .NET Framework 指南

示例 1

下面的簡單示例展示一個 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 方法實現。如果需要,派生類可調用或重寫該方法。

接口中的事件

事件和字段之間的另一個差異是,事件可放在接口中,而字段不能。當實現接口時,實現類必須在實現接口的類中提供相應的事件。

.NET Framework 指南

盡管 C# 語言允許事件使用任意委托類型,但“.NET Framework”對於應為事件使用的委托類型有一些更嚴格的指南。如果打算將您的組件與“.NET Framework”一起使用,您可能希望遵守這些指南。

“.NET Framework”指南指示用於事件的委托類型應采用兩個參數:指示事件源的“對象源”參數和封裝事件的其他任何相關信息的“e”參數。“e”參數的類型應從 EventArgs 類派生。對於不使用其他任何信息的事件,“.NET Framework”已定義了一個適當的委托類型:EventHandler

示例 2

下面的示例是“示例 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] 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved