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

c#事件 概述

編輯:關於C#
 

任何編寫過圖形用戶界面(GUI)軟件的開發人員都熟悉事件處理編程,當用戶與GUI控制進行交互時(例如點擊表格上的按鈕),作為上述事件的反應,就會執行一個或多個方法。沒有用戶的參與,事件也可能執行。事件處理程序是對象的方法,是根據應用程序中發生的事件而執行的。為了理解.Net框架下的事件處理模式,我們需要理解代理的概念。
C#中的代理
C#中的代理允許我們將一個類中的方法傳遞給其他類的對象。我們能夠將類A中的方法m封裝為一個代理,傳遞給類B,類B能夠調用類A中的方法m,靜態和實例方法都可以傳送。C++軟件開發人員應該對這一概念非常熟悉,在C++中,開發人員能夠以參數的形式使用函數指針將函數傳遞給同理個類或其他類中的方法。代理的概念是在Visulal J++中引入的,然後又被帶到了C#中。在.Net框架中C#的代理是以從System.Delegate中繼承的類的形式實現的。使用代理需要4個步驟:
1、定義一個輸入參數與要進行封裝的方法完全相同的代理對象。
2、定義所有輸入參數與在第1步中定義的代理對象相同的方法。
3、創建代理對象,並與希望封裝的方法進行連接。
4、通過代理對象調用封裝的方法。
下面的C#代碼通過實現一個代理、4個類舉例說明了上面的4個步驟:
using System;
//步驟1:定義一個具有被封裝方法輸入參數的代理對象
public delegate void MyDelegate(string input);
//步驟2:定義與定義的代理對象具有相同輸入參數的方法
class MyClass1{
public void delegateMethod1(string input){
Console.WriteLine("This is delegateMethod1 and the input to the method is {0}",input);
}
public void delegateMethod2(string input){
Console.WriteLine("This is delegateMethod2 and the input to the method is {0}",input);
}
}
//步驟3:創建代理對象,插入方法
class MyClass2{
public MyDelegate createDelegate(){
MyClass1 c2=new MyClass1();
MyDelegate d1 = new MyDelegate(c2.delegateMethod1);
MyDelegate d2 = new MyDelegate(c2.delegateMethod2);
MyDelegate d3 = d1 + d2;
return d3;
}
}
//步驟4:通過代理調用被封裝的方法。
class MyClass3{
public void callDelegate(MyDelegate d,string input){
d(input);
}
}
class Driver{
static void Main(string[] args){
MyClass2 c2 = new MyClass2();
MyDelegate d = c2.createDelegate();
MyClass3 c3 = new MyClass3();
c3.callDelegate(d,"Calling the delegate");
}
}

C#中的事件處理程序
C#中的事件處理程序是一個帶有特定輸入參數的代理,如下所示:
public delegate void MyEventHandler(object sender, MyEventArgs e);

上面定義中的第一個參數(sender)指定了發生事件的對象,第二個參數(e)存儲著在事件處理程序中要用到的數據。MyEventArgs類是繼承EventArgs類得來的,EventArgs類是MouseEventArgs、ListChangedEventArgs等更專業化的類的基礎類。對於GUI事件,我們可以使用這些特定的EventArgs類的對象,而無需自己創建特定的EventArgs類。然而,對於非GUI事件而言,我們仍然需要創建自己的特定的EventArgs類,存儲希望向代理對象傳遞的數據。我們可以通過繼承EventArgs類創建自己特定的EventArgs類:
public class MyEventArgs EventArgs{
public string m_myEventArgumentdata;
}
在事件處理程序中,代理對象的調用需要用到event關健字,如下所示:
public event MyEventHandler MyEvent;
下面我們將建立二個類,體會.Net框架中事件處理機制的工作原理。在對代理的討論的第二個步驟中,要求我們定義與定義的代理有完全相同的輸入參數的方法。在我們的例子中,類A將提供事件處理程序(與代理對象具有相同輸入參數的方法。),它將創建代理對象(對代理討論中的第三步)並安裝事件處理程序。類A然後會將代理對象傳遞給類B。當類B中有事件出現時,它就會執行類A中的事件處理程序方法。
using System;
//步驟1:創建代理對象
public delegate void MyHandler1(object sender,MyEventArgs e);
public delegate void MyHandler2(object sender,MyEventArgs e);
//步驟2:創建事件處理程序方法
class A{
public const string m_id="Class A";
public void OnHandler1(object sender,MyEventArgs e){
Console.WriteLine("I am in OnHandler1 and MyEventArgs is {0}", e.m_id);
}
public void OnHandler2(object sender,MyEventArgs e){
Console.WriteLine("I am in OnHandler2 and MyEventArgs is {0}", e.m_id);
}
//步驟3:創建代理,安裝事件處理程序,並向啟動事件的對象注冊。
public A(B b){
MyHandler1 d1=new MyHandler1(OnHandler1);
MyHandler2 d2=new MyHandler2(OnHandler2);
b.Event1 +=d1;
b.Event2 +=d2;
}
}
//步驟4:通過代理調用封裝的方法。
class B{
public event MyHandler1 Event1;
public event MyHandler2 Event2;
public void FireEvent1(MyEventArgs e){
if(Event1 != null){
Event1(this,e);
}
}
public void FireEvent2(MyEventArgs e){
if(Event2 != null){
Event2(this,e);
}
}
}
public class MyEventArgs EventArgs{
public string m_id;
}
public class Driver{
public static void Main(){
B b= new B();
A a= new A(b);
MyEventArgs e1=new MyEventArgs();
MyEventArgs e2=new MyEventArgs();
e1.m_id ="Event args for event 1";
e2.m_id ="Event args for event 2";
b.FireEvent1(e1);
b.FireEvent2(e2);
}
}

C#中的GUI事件處理
Windows Forms(支持GUI應用程序的.NET框架)中的事件處理使用.NET事件處理模式。我們下面將應用這種模式編寫一個簡單的應用程序,該應用程序有一個繼承自System.Windows.Forms.Form類的MyForm類。如果仔細地研究一下代碼和其中的三行注釋,就會發現其實我們無須定義代理和使用event關健字調用這些代理,因為我們已經可以使用GUI控制(表格、按鈕等)的事件(鼠標點擊等),代理就是System.EventHandler。當然了,我們仍然需要定義方法,創建代理對象(System.EventHandler),並在代理對象中安裝方法,一旦有事件發生,方法就會開始執行。
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

public class MyForm Form{
private Button m_nameButton;
private Button m_clearButton;
private Label m_nameLabel;

private Container m_components = null;

public MyForm(){
initializeComponents();
}
private void initializeComponents(){
m_nameLabel=new Label();
m_nameButton = new Button();
m_clearButton = new Button();

SuspendLayout();

m_nameLabel.Location=new Point(16,16);
m_nameLabel.Text="Click NAME button, please";
m_nameLabel.Size=new Size(300,23);

m_nameButton.Location=new Point(16,120);
m_nameButton.Size=new Size(176, 23);
m_nameButton.Text="NAME";
//創建代理,並安裝方法,將代理捆綁在按鈕的Click事件上
m_nameButton.Click += new System.EventHandler(NameButtonClicked);

m_clearButton.Location=new Point(16,152);
m_clearButton.Size=new Size(176,23);
m_clearButton.Text="CLEAR";
//創建代理,並安裝方法,將代理捆綁在按鈕的Click事件上
m_clearButton.Click += new System.EventHandler(ClearButtonClicked);

this.ClientSize = new Size(292, 271);
this.Controls.AddRange(new Control[] {m_nameLabel,m_nameButton,m_clearButton});
this.ResumeLayout(false);
}
//定義輸入參數與代理完全相同的方法
private void NameButtonClicked(object sender, EventArgs e){
m_nameLabel.Text="My name is john, please click CLEAR button to clear it";
}
private void ClearButtonClicked(object sender,EventArgs e){
m_nameLabel.Text="Click NAME button, please";
}
public static void Main(){
Application.Run(new MyForm());
}
}

結束語
Java和Smalltalk等其他的面向對象的編程語言中都沒有代理的概念,這一概念是在C#中新引進的,它源自於C++和J++。我希望上面的討論使第一次使用面向對象的編程語言時就使用C#語言的編程人員能夠弄明白代理的概念。如果使用Visual Studio IDE作為C# GUI的開發環境,無需編寫代碼就能夠將代理中的方法與由GUI控制生成的事件(例如用鼠標點擊按鈕等)連接在一起,當然了,我們還是應當知道這是怎麼回事

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