淺析C#的事件處理和自訂事件

來源:互聯網
上載者:User

淺析C#的事件處理和自訂事件

一、瞭解C#中的預定義事件處理機制

在寫代碼前我們先來熟悉.net架構中和事件有關的類和委託,瞭解C#中預定義事件的處理。

EventArgs是包含事件數目據的類的基類,用於傳遞事件的細節。

EventHandler是一個委託聲明如下

public delegate void EventHandler( object sender , EventArgs e )

注意這裡的參數,前者是一個對象(其實這裡傳遞的是對象的引用,如果是button1的click事件則sender就是button1),後面是包含事件數目據的類的基類。

下面我們研究一下Button類看看其中的事件聲明(使用WinCV工具查看),以Click事件為例。

public event EventHandler Click;

這裡定義了一個EventHandler類型的事件Click

前面的內容都是C#在類庫中已經為我們定義好了的。下面我們來看編程時產生的代碼。

private void button1_Click(object sender, System.EventArgs e)
{
...
}

這是我們和button1_click事件所對應的方法。注意方法的參數符合委託中的簽名(既參數列表)。那我們怎麼把這個方法和事件聯絡起來呢,請看下面的代碼。

this.button1.Click += new System.EventHandler(this.button1_Click);

把this.button1_Click方法綁定到this.button1.Click事件。

下面我們研究一下C#事件處理的工作流程,首先系統會在為我們建立一個在後台監聽事件的對象(如果是button1的事件那麼監聽事件的就是button1),這個對象用來產生事件,如果有某個使用者事件發生則產生對應的應用程式事件,然後執行訂閱了事件的所有方法。

二、簡單的自訂事件(1)

首先我們需要定義一個類來監聽用戶端事件,這裡我們監聽鍵盤的輸入。

定義一個委託。

public delegate void UserRequest(object sender,EventArgs e);

前面的object用來傳遞事件的發生者,後面的EventArgs用來傳遞事件的細節,現在暫時沒什麼用處,一會後面的例子中將使用。

下面定義一個此委託類型類型的事件

public event UserRequest OnUserRequest;

下面我們來做一個死迴圈

public void Run()
{
bool finished=false;
do
{
if (Console.ReadLine()=="h")
{
OnUserRequest(this,new EventArgs());
}
}while(!finished);
}

此代碼不斷的要求使用者輸入字元,如果輸入的結果是h,則觸發OnUserRequest事件,事件的觸發者是本身(this),事件細節無(沒有傳遞任何參數的EventArgs執行個體)。我們給這個類取名為UserInputMonitor。

下面我們要做的是定義用戶端的類 首先得執行個體化UserInputMonitor類 UserInputMonitor monitor=new UserInputMonitor();

然後我們定義一個方法。

private void ShowMessage(object sender,EventArgs e)
{
Console.WriteLine("HaHa!!");
}

最後要做的是把這個方法和事件聯絡起來(訂閱事件),我們把它寫到庫戶端類的建構函式裡。

Client(UserInputMonitor m)
{
m.OnUserRequest+=new UserInputMonitor.UserRequest(this.ShowMessage);
//m.OnUserRequest+=new m.UserRequest(this.ShowMessage);

//注意這種寫法是錯誤的,因為委託是靜態

}

下面建立用戶端的執行個體。

new Client(monitor);

對了,別忘了讓monitor開始監聽事件。

monitor.run();

大功告成,代碼如下:

using System;
class UserInputMonitor
{
public delegate void UserRequest(object sender,EventArgs e);
//定義委託
public event UserRequest OnUserRequest;
//此委託類型類型的事件
public void Run()
{
bool finished=false;
do
{
if (Console.ReadLine()=="h")
{
OnUserRequest(this,new EventArgs());
}
}while(!finished);
}
}

public class Client
{
public static void Main()
{
UserInputMonitor monitor=new UserInputMonitor();
new Client(monitor);
monitor.Run();
}
private void ShowMessage(object sender,EventArgs e)
{
Console.WriteLine("HaHa!!");
}
Client(UserInputMonitor m)
{
m.OnUserRequest+=new UserInputMonitor.UserRequest(this.ShowMessage);
//m.OnUserRequest+=new m.UserRequest(this.ShowMessage);
//注意這種寫法是錯誤的,因為委託是靜態
}
}

 

 

三、進一步研究C#中的預定義事件處理機制

可能大家發現在C#中有些事件和前面的似乎不太一樣。例如

private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{

}

this.textBox1.KeyPress+=newSystem.Windows.Forms.KeyPressEventHandler(this.textBox1_KeyPress);

這裡使用了KeyPressEventArgs而不是EventArgs作為參數。這裡使用了KeyEventHandler委託,而不是EventHandler委託。

KeyPressEventArgs是EventArgs的衍生類別,而KeyEventHandler的聲明如下

public delegate void KeyEventHandler( object sender , KeyEventArgs e );

是參數為KeyEventArgs的委託。那為什麼KeyPress事件要這麼做呢,我們可以從兩個類的建構函式來找答案。

public EventArgs();

public KeyPressEventArgs(char keyChar);

這裡的keyData是什麼,是用來傳遞我們按下了哪個鍵的,哈。

我在KeyEventArgs中又發現了屬性

public char KeyChar { get; }

進一步證明了我的理論。下面我們來做一個類似的例子來協助理解。

四、簡單的自訂事件(2)

拿我們上面做的例子來改。

我們也定義一個EventArgs(類似KeyEventArgs)取名MyEventArgs,定義一個建構函式public MyEventArgs(char keyChar),同樣我們也設定相應的屬性。代碼如下

using System;
class MyMyEventArgs:EventArgs
{
private char keyChar;
public MyMyEventArgs(char keyChar)
{
this.keychar=keychar;
}
public char KeyChar
{
get
{
return keyChar;
}
}
}

因為現在要監聽多個鍵了,我們得改寫監聽器的類中的do...while部分。改寫委託,改寫用戶端傳遞的參數。好了最終代碼如下,好累

using System;
class MyEventArgs:EventArgs
{
private char keyChar;
public MyEventArgs(char keyChar)
{
this.keyChar=keyChar;
}
public char KeyChar
{
get
{
return keyChar;
}
}
}

class UserInputMonitor
{
public delegate void UserRequest(object sender,MyEventArgs e);
//定義委託
public event UserRequest OnUserRequest;
//此委託類型類型的事件
public void Run()
{
bool finished=false;
do
{
string inputString= Console.ReadLine();
if (inputString!="")
OnUserRequest(this,new MyEventArgs(inputString[0]));
}while(!finished);
}
}

public class Client
{
public static void Main()
{
UserInputMonitor monitor=new UserInputMonitor();
new Client(monitor);
monitor.Run();
}
private void ShowMessage(object sender,MyEventArgs e)
{
Console.WriteLine("捕捉到:{0}",e.KeyChar);
}
Client(UserInputMonitor m)
{
m.OnUserRequest+=new UserInputMonitor.UserRequest(this.ShowMessage);
//m.OnUserRequest+=new m.UserRequest(this.ShowMessage);
//注意這種寫法是錯誤的,因為委託是靜態
}
}

 

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.