古詩詞大全網 - 藝術簽名 - 找壹個C#事件處理的例子。

找壹個C#事件處理的例子。

6.2自定義事件

自定義事件是委托的典型應用!當開發人員編寫WinForm或ASP.NET應用程序時,他們將使用Button的Click事件。那麽,這種事件聯系機制是如何實現的呢?我們能寫自己定義的事件嗎?另外,我們什麽時候需要編寫自己定義的事件?

6.2.1為什麽要使用自定義事件?

很多開發者會問作者這個問題——“為什麽要自己寫事件?控件中集成了很多事件,這還不夠我們用嗎?”。

在實現中,如果不清楚如何編寫自定義事件,就很難開發出真正可用的應用。主要原因如下:

1.自定義控件

通常,為了減少重復的界面功能代碼量,開發者往往會開發壹些用戶控件或自定義控件。這個時候,我們就會出現問題。微軟提供的控件包含了很多事件,那麽我們自己寫的控件會有很多事件嗎?

2.自行編寫的組件和類庫

事件並不僅限於UI層中的控件類。許多基礎類也包含事件,如SqlConnection類。該類的類視圖如下:

InfoMessage事件包含在該類中,用於“在SQL Server返回警告或信息性消息時發生”。換句話說,我們自己寫壹個類的時候,經常會發生壹種特殊的數據傳輸情況,就是數據傳輸的方向是自下而上的。為了解釋這種“自下而上”的交付模式,我們先來看看壹個應用程序的層次結構圖:

上圖是壹個常規Socket通信軟件的三層架構圖。客戶端和服務器的接口是兩個“EXE”程序,但是為了更好的管理系統邏輯,我們通常在業務邏輯層把所有的通信邏輯封裝到兩個“DLL”文件中。圖中箭頭方向是整個系統功能的實現,通過從界面的“EXE”調用底層“DLL”來實現。

但是,所有通信函數都是在DLL中定義的類中實現的。那麽,當客戶端的DLL向服務器的DLL發送消息,被服務器的DLL截獲時,服務器接口的“EXE”是怎麽知道的呢?我們平時用QQ和MSN的時候有沒有想過這個問題?

這時,我們剛剛提到的問題又出現了——“自下而上”,即下層“DLL”中的類通知上層“EXE”中的接口。不能再用DLL調用EXE了!

註意:通常情況下。NET平臺可以引用EXE,但如上圖所示,EXE已經引用了DLL,IDE將不再允許DLL引用EXE,以防止循環引用造成死鎖。即使IDE允許我們用DLL引用EXE,但是引用後創建的實例和當前運行接口的實例位於不同的內存中,所以任何操作都不會生效。

此時,我們可以使用委托實現的事件機制來解決問題!

控制中的事件

為了理解事件機制,讓我們從控件中的事件開始。我們以Button的Click事件為例來說明。

當開發人員雙擊按鈕時,IDE會將設計器轉到代碼視圖,為我們生成壹個事件回調的方法,如下圖所示:

註意:button1_Click這裏不是事件,只是事件發生時調用的方法!

我們的問題是,為什麽在按鈕1的Click事件之後調用Button1 _ Click方法?事實上,當我們雙擊Button1時,IDE會自動添加壹段代碼,這段代碼位於“Form1。designer . cs”(Form 1.1不包括Form 1。Designer.cs),"表單65438+"

打開表單1。Designer.cs,展開“InitializeComponent()”方法找到第42行,如下圖所示:

我們可以看到下面的代碼:

this.button1。點擊+=新系統。EventHandler(this . button 1 _ Click);

其實這個代碼就是所謂的事件註冊碼。這段代碼的意思是:如果this.button1的Click事件發生,轉到this。button1_Click方法進行處理。

為了更好地理解事件註冊過程,我們首先修改第42行代碼,如下圖所示:

在這裏,我們將把原

this.button1。點擊+=新系統。EventHandler(this . button 1 _ Click);

修改為

this.button1。單擊=新系統。EventHandler(this . button 1 _ Click);

在這個程序中,這裏的修改是為了更好的理解,當然這個寫法是語法錯誤的。

下面我們來分析壹下:

首先,觀察“=”右邊的表達式。

新系統。EventHandler(this . button 1 _ Click);

通過6.1.1壹節的解釋,可以發現這段代碼實際上是創建了壹個委托類型的實例,並使委托指向this.button1_Click方法。也就是說,在程序運行的“某個時刻”,系統會通過這個委托實例間接調用this.button1_Click方法。

然後,我們來觀察“=”左邊的表達式。在C風格語言中,“=”是壹個賦值表達式,即“=”兩邊表達式的數據類型應該相同。因此,由於“=”右側的表達式是委托類型的實例(系統。EventHandler),this.button1。點擊也應該是委托類型(系統。EventHandler)。

通過上面的解釋,我們得到壹個信息,前壹段的事件註冊碼使得this.button1。Click和system . eventhandler(this . button 1 _ click)指向同壹個內存空間。簡單來說就是this.button1。Click指向this.button1_Click方法,並調用this.button1。Click相當於調用this.button1_Click方法。所以我們說當this.button1的Click事件發生時,就會調用this.button1_Click的方法。

當程序運行時,系統將檢查這個按鈕1是否被點擊。如果它被點擊,它將調用button1。點擊內部按鈕1。此時,將執行Windows窗口中的button1_Click方法。

當然,活動註冊碼完全可以手寫。因為,除了控件中的事件註冊代碼是自動生成的,其他類中的事件註冊都是手寫的。手動註冊事件的方法如下:

首先,妳可以在事件發生之前在任何代碼中添加壹個事件(通常在窗口構造方法中)。讓我們手動註冊button1的MouseMove事件,如下圖所示:

當我們寫完“=”後,會出現提示“按TAB插入”。此時我們只需要按兩次“TAB”鍵,事件註冊和用於回調的方法就會添加到代碼窗口中,如下圖所示:

自動生成的代碼將this.button1的MouseMove事件指向button1_MouseMove方法。這個手寫代碼和IDE自動生成的代碼壹模壹樣。

當然,作為壹個控件的事件,我們可以自動生成。如果想自動生成button1的其他事件,只需查看button1的屬性窗口,點擊按鈕,就會出現該控件的事件列表,如下圖所示:

然後雙擊妳想要的事件,代碼就會自動生成。

在前面的代碼中,為了更好地理解事件註冊,我們曾經

this.button1。點擊+=新系統。EventHandler(this . button 1 _ Click);

修改為

this.button1。單擊=新系統。EventHandler(this . button 1 _ Click);

我們會發現,無論是自己編寫的事件註冊代碼,還是自動生成的代碼,都是用“+=”實現的。其實作為事件註冊代碼,我們只能用“+=”來實現註冊。簡單地用“=”是語法錯誤的!!!

“+=”運算符是C風格語言中的常見運算符,例如

int I = 0;

I+= 1;

等同於

int I = 0;

I = I+1;

因此,

this.button1。點擊+=新系統。EventHandler(this . button 1 _ Click);

原則上等同於

this.button1。點擊= this.button1。點擊+

新系統。EventHandler(this . button 1 _ Click);

用自然語言來描述上面的代碼就是“壹個委托=這個委托本身+另壹個委托”。那麽添加委托是什麽意思呢?

6.1.3節我們討論了組播委托,事件本身就是壹個委托,所有的委托都是從系統中派生出來的。在6.1.3節中,我們曾經演示過,添加多委托類型意味著這些委托實例存儲在多播委托的調用鏈中。當調用多播委托時,多播委托

使用多播委托的原則,我們可以向壹個事件註冊多個方法,如下所示:

this.button1。點擊+=新系統。EventHandler(this . button 1 _ Click);

this.button1。點擊+=新系統。EventHandler(this . button 1 _ click 1);

this.button1。點擊+=新系統。EventHandler(this . button 1 _ click 2);

上面的代碼在button1的Click事件中註冊了三個方法。當觸發button1的Click事件時,將依次調用button1_Click、button1_Click、button1_Click2方法。這樣做的好處是,我們可以把邏輯完全獨立的多個函數和操作放在不同的方法中。當事件發生時,這些方法將被調用,以便實現我需要的級聯操作。

6.2.3控件中事件的回調方法

說完了事件的註冊,再來說說事件的回調方法。首先,我們必須再次回顧事件註冊的代碼:

this.button1。點擊+=新系統。EventHandler(this . button 1 _ Click);

在上面的代碼中,壹個系統的實例。EventHandler委托類型是指向this.button1_Click的方法通過使用" new system。Eventhandler (this。按鈕1 _ click)”。從6.1.1節提到的內容我們知道,如果妳想讓壹個委托指向壹個方法,那麽這個委托和被指向的方法必須有相同的簽名(有相同的參數列表和相同的返回值)。因此,系統。EventHandler類型和this.button1_Click方法具有相同的簽名。讓我們來看看系統的簽名是什麽。EventHandler委托看起來像:

公共委托void EventHandler(

對象發送者,

EventArgs e

)

系統的簽名。EventHandler為:返回值為void有兩個參數,objectsender和eventargse。所以button1_Click方法也有同樣的形式,代碼如下:

私有void button1_Click(對象發送方,EventArgs e)

{

}

其實我們能看到的事件回調方法的簽名基本都很少,只是第二個參數略有不同。下面,我們將解釋這種方法的參數。

對象發送者

從這個參數的命名就可以看出它的作用。發送者的意思是:觸發這個事件的人就是發送者。因為理論上所有類型都可以包含事件,所以發送方的類型被定義為對象類型。當多個事件同時指向壹個事件回調方法時,可以用它來區分哪個類觸發了該事件,以便做出不同的處理。此時,需要對參數發送方進行處理。

案例操作020603:多個事件指向同壹個回調方法。

首先,添加三個按鈕和壹個文本框。

界面如下:

然後,在主窗口中添加壹個方法ButtonClick,將由這三個按鈕的Click事件調用。

代碼如下:

受保護的void ButtonClick(對象發送方,EventArgs e)

{

Button bt =發件人as按鈕;

This.textBox1。Text = "我是:"+bt。文本;

}

在上面的代碼中,為了知道哪個按鈕被點擊了,我們將sender轉換為Button類型。

我們來指定這三個按鈕的Click事件回調方法。

首先切換到button1的屬性窗口(F4),點擊“”按鈕,找到“Click”事件,將調用的方法設置為ButtonClick,如下圖所示。

然後,button2、button3的Click事件也以同樣的方式設置,都指向ButtonClick方法。

最後運行程序,以下是運行情況:

點擊按鈕1:

點擊按鈕2:

點擊按鈕3:

EventArgs e

EventArgs類型是壹個事件參數,當事件發生時,可以通過它傳遞壹些數據。當然,EventArgs類本身不能傳遞任何數據。該類的類視圖如下:

從班級來看,不難發現這個班級成員很少。通常,如果要傳遞數據,事件參數類壹般會是EventArgs類的派生類。例如,TextBox類的KeyDown事件中的事件參數是KeyEventArgs類型的參數,事件回調方法的原型如下:

私有void textBox1_KeyDown(對象發送方,KeyEventArgs e)

{

}

KeyEventArgs類的類視圖如下:

這個類有三個屬性:“Alt”、“Control”和“Shift”,分別用來表示在按下鍵盤的壹個鍵的同時,這三個功能鍵是否被按下。

此外,“KeyCode”屬性可用於指示當前用戶按下的鍵名稱。

在下壹節中,我們將解釋如何編寫自定義事件參數。

案例操作020604:使用TextBox的KeyDown事件模擬QQ聊天窗口。

創建壹個新的Windows窗口,包括以下控件

RichTextBox控件(rtbMessage):用於顯示聊天信息。

壹個文本框控件(tbxInput):用於輸入聊天信息。

壹個按鈕控件(btSubmit):用於提交

界面如下:

這些功能如下:

單擊按鈕將消息發送到上面的RichTextBox。當然,如果按“Ctrl+Enter”,也可以將文本傳入RichTextBox。

首先,我們用以下代碼在Windows窗口中添加壹個方法:

公共空顯示()

{

this . rtb message . appendtext(this . tbx input。text+" n ");

this . tbx input . text = " ";

}

該方法的功能是將文本框中的文本添加到RichTextBox中。

接下來,編寫按鈕Click事件,代碼如下:

private void btSubmit_Click(對象發送方,EventArgs e)

{

這個。顯示();

}

接下來,編寫TextBox的KeyDown事件,代碼如下:

私有void tbxInput_KeyDown(對象發送方,KeyEventArgs e)

{

if(e . Control = = true & amp;& ampe .鍵碼。ToString ()=="Return ")

{

這個。顯示();

}

}

此方法首先檢測用戶在執行顯示操作之前是否同時按下了Control和enter鍵。

程序運行的效果如下:

按Control+ Enter後會顯示文字,效果如下:

C#委托和事件問題

20

[標簽:c#委托,事件問題]

委托和時間我不太懂。看了《如何申報委托》就懂了。但是,書裏什麽時候講到如何實例化委托使用場合,就不太清楚了。聲明的委托,類中委托的參數與聲明的參數不同。很糾結。求高手給我詳細講解壹下委托的使用方法。

答案:10人氣:10求解時間:2011-08-09 07:52。

滿意的回答

陽性率:0%

委托是C#中事件機制的核心,在網絡上經常被神話。把它比作壹個門檻,過了的人很開心,沒過的人在門外焦慮無語。

本文將與您討論委托的實現和觀察者設計模式之間的關系。

學習C#的時候,委托對我來說是壹個門檻,而且是非常高的門檻。我幾次把它放在門檻上,然後就壹頭栽了下去。我害怕它已經很久了。看了很多網上的文章,理解起來又辛苦又費力。不是人說話難聽,而是人太膚淺。但是網上的文章多是用例子和事件機制來解釋,可能C++程序員更好理解。說白了,委托就是壹種類似指針的東西。

在學習委托之前,我們先了解壹下觀察者設計模式,委托和時間很好的實現了這個模式。先在head中舉壹個例子,然後舉壹個天氣預報板的例子,將其轉化為C#中基於委托的實現。

這家出版社打算出版壹本雜誌。為了更好地適應這個市場,出版社可謂是花樣百出,結果也有不少讀者訂閱了這本雜誌。我們把出版社當做壹個主題或者說壹個觀察者,把讀者當做壹個觀察者。出版社更新雜誌時,會通知讀者獲取最新內容。因為雜誌越來越受歡迎,所以吸引了越來越多的讀者。如果新讀者想得到這本雜誌,他們必須向出版社訂購。這個過程被理解為註冊。後來讀者A不滿意,不想訂了,就提出了註銷申請,然後出版社把讀者A的名單去掉了,新壹期雜誌出來,不會通知讀者A去拿資料。壹旦讀者A厭倦了,又想要雜誌,他就不得不重新訂購。

從上面的例子可以看出,出版社(主體或被觀察)有幾個動作,接受壹個讀者的訂購請求,去掉壹個讀者,給每個讀者分發最新的雜誌。

下面的代碼演示如何實現基於委托的系統:

public class Public Publisher {

名單劃線員;//保存新的讀者。

公共發布者(){

this . scribers = new ArrayList();

}

公共無效註冊登記員(登記員sc) {

scribers . add(sc);

}

公共void removeScriber(Scriber sc) {

int index = scribers . index of(sc);

if(index & gt;0)

scribers . remove(sc);

}

//有新的雜誌更新時會執行。

public void newMagazine() {

for(int I = 0;我& lt劃線器.長度;i++) {

Scriber sc =(Scriber)scribers . get(I);

sc . update();

}

}

}

公共類劃線器{

//包含對主題的引用。

私人出版商pub

公共抄寫員(出版商出版公司){

this.pub = pub

pub.registerScriber(這個);//寄存器

}

公共void更新(){

Sysout.out.println("妳有新雜誌了!!");

}

}

公共類測試{

公共靜態void main(String[] args) {

Publisher pub = new Publisher();

劃線員sc =新劃線員(pub);

pub . new magazine();

}

}

/*輸出:

妳有新雜誌了!!

*/

上面壹個讀者和出版社的例子演示了壹個簡單的觀察者模型。當壹本新雜誌出版時,每個讀者都會得到通知。我們可以定義多個讀者,也就是說,發布者和讀者的關系是1。理解觀察者模式,