事件及其編程方法探討 事件驅(qū)動(dòng)編程的一般方法
發(fā)布時(shí)間:2020-02-16 來(lái)源: 日記大全 點(diǎn)擊:
摘要:在面向?qū)ο缶幊汰h(huán)境下,對(duì)于某種控件都給定了相應(yīng)的屬性及事件(Even),一般用戶無(wú)法添加屬性、事件及其事件驅(qū)動(dòng)程序。在C#語(yǔ)言中,為用戶提供了類的屬性成員,類屬性成員狀態(tài)的改變,通過(guò)事件代理的關(guān)聯(lián),可以調(diào)用相應(yīng)的事件處理方法。本文介紹C#語(yǔ)言中的屬性成員、事件代理的定義,通過(guò)事件代理調(diào)用事件處理方法等技術(shù),并通過(guò)實(shí)例程序進(jìn)行必要的說(shuō)明。
關(guān)鍵詞:屬性;代理;事件;多播事件
中圖分類號(hào):TP312 文獻(xiàn)標(biāo)識(shí)碼:A
1 事件及基本概念
對(duì)于事件(Even),熟悉可視化編程的人員并不陌生。例如,在單擊某個(gè)“按鈕”后,系統(tǒng)應(yīng)該對(duì)此“單擊”事件作出相應(yīng)的反映,如播放一曲MP3樂(lè)曲或顯示一張圖表等。
在C#語(yǔ)言中,事件的發(fā)生可以由用戶的操作使然;也可以由程序邏輯觸發(fā),例如類的某個(gè)對(duì)象狀態(tài)發(fā)生改變將引起程序?qū)?duì)象狀態(tài)的改變并做出相應(yīng)的處理。觸發(fā)事件的對(duì)象稱為事件的發(fā)送者,接收事件的對(duì)象稱為事件的接收者。
C#語(yǔ)言的事件處理機(jī)制具有如下的特征:
數(shù)據(jù)成員、方法、事件和屬性都是類的一個(gè)成員;在.NET框架中,事件是將事件發(fā)送者與事件的接收者相關(guān)聯(lián)的一種代理類,也就是事件機(jī)制是通過(guò)代理實(shí)現(xiàn)的。當(dāng)事件被觸發(fā)時(shí),由事件的代理通知處理該事件的方法。
2 C#語(yǔ)言中的屬性成員
屬性常用來(lái)封裝類的數(shù)據(jù),常見(jiàn)的屬性有對(duì)象名、字體、顏色等。使用屬性的好處是使應(yīng)用程序看起來(lái)更加直觀。屬性的用處是限制外部對(duì)類中成員變量的存取訪問(wèn)。
2.1屬性的定義
C#屬性定義的一般格式為:
class 類名
{ [修飾符] 數(shù)據(jù)類型 屬性名
{訪問(wèn)函數(shù)體}
}
其中修飾符可以為:public、private、static、protected、internal、virtual、override、 abstract等。如果修飾符為abstract,則訪問(wèn)函數(shù)體只包含“;”,如果是其它修飾符,則訪問(wèn)函數(shù)體要包含訪問(wèn)函數(shù)體所必須的代碼。數(shù)據(jù)類型表示屬性成員值的數(shù)據(jù)類型。{}中的代碼是執(zhí)行屬性過(guò)程的程序代碼,一般包括get和set兩個(gè)訪問(wèn)函數(shù)體。
2.2 相關(guān)函數(shù)的實(shí)現(xiàn)
首先要對(duì)包含get和set兩個(gè)訪問(wèn)函數(shù)體的屬性進(jìn)行定義,通過(guò) get 和 set 訪問(wèn)函數(shù)將專用數(shù)據(jù)成員和公共屬性關(guān)聯(lián)起來(lái)。根據(jù)使用情況不同,可以只用get或者set,也可以同時(shí)使用get和set。其中,get:用來(lái)讀取數(shù)據(jù)成員的值;set:用來(lái)設(shè)置數(shù)據(jù)成員的值,其操作往往是“數(shù)據(jù)成員=value;”。
2.3 類的屬性編程實(shí)例
using System;
namespace ConAppshuxjuli
{class point
{ int my_x, my_y ;//定義數(shù)據(jù)成員
publicintx //實(shí)現(xiàn)屬性成員x
{get{ return my_x;}
set{ my_x=value;}
}
public int y //實(shí)現(xiàn)屬性成員y
{ get { return my_y;}
set { my_y = value; }
}
}
class MyApp
{ static void Main(string[] args)
{point starting = new point();
point ending = new point();
//對(duì)屬性成員賦值
starting.x = 1;starting.y=3;
ending.x = 15; ending.y = 17;
// 對(duì)starting.x等屬性成員引用
Console.WriteLine(“起始點(diǎn)坐標(biāo)是:
[{0},{1}]”,starting.x,starting.y);
Console.WriteLine(“終止點(diǎn)坐標(biāo)是:
[{0},{1}]”, ending.x, ending.y);
Console.Read();
} }}
上述程序的運(yùn)行結(jié)果為:
3 事件處理程序
事件處理程序編寫步驟為:首先要定義一個(gè)事件代理,創(chuàng)建包含事件成員的類(事件類),編寫事件處理方法,將事件處理方法和事件關(guān)聯(lián)起來(lái)等。
3.1 定義事件代理
定義事件代理的格式為:
[修飾符] delegate void 代理名([觸發(fā)事件的對(duì)象,事件參數(shù)]\);
例如:delegate voidCharEventHandler
(Objectsender, CharEventArgs e);
關(guān)于代理的有關(guān)內(nèi)容可查閱筆者撰寫的《代理及其編程方法》一文或其它有關(guān)資料。
3.2 定義一個(gè)包含事件信息的類
定義一個(gè)包含事件信息類的格式為:
public class XXEventArgs:EventArgs
{//類的具體定義}
例如:
public class CharEventArgs:EventArgs
{ public char CurrChar;//字符變量
public CharEventArgs(char CurrChar)
{ this.CurrChar = CurrChar;}
……
。
3.3 創(chuàng)建事件類
創(chuàng)建包含事件成員的類(又稱為事件類),首先要定義事件成員,然后編寫觸發(fā)事件的方法或?qū)傩缘瘸蓡T。
(1)定義事件成員的格式為:
[修飾符] event 事件代理名 事件名
上述事件代理名必須是在3.1定義事件代理名。
(2)編寫觸發(fā)事件的方法或?qū)傩缘瘸蓡T
class CharChecker
{char curr_char;
//定義事件成員
public event CharEventHandler CharTest;
//觸發(fā)事件的屬性
public char Curr_Char
{ get { return curr_char; }
set
{ if (CharTest != null)
{ CharEventArgs myevent = new
CharEventArgs(value);
//事件成員調(diào)用事件處理方法
CharTest(this, myevent);
curr_char = myevent.CurrChar;
} } } }
3.4 編寫事件處理方法
編寫相應(yīng)的事件處理方法。例如:
static void Change_X(Object source,
CharEventArgs e)
{ if(e.CurrChar==?x?|| e.CurrChar
==?X?)
{ Console.Write(“觸發(fā)的字符是x ,”);
Console.Write(“把 x 替換為:”);
e.CurrChar =?三?;
}
else
Console.Write(“觸發(fā)的字符不是x ,”);
……
}
3.5 事件處理方法和事件相關(guān)聯(lián)
首先要?jiǎng)?chuàng)建事件類的對(duì)象。例如:
CharChecker chartester = new
CharChecker();
再將事件處理方法與事件對(duì)象相關(guān)聯(lián),其格式為:
事件類對(duì)象名.事件成員+=new事件代理名
(事件處理方法名列表);
例如:
chartester.CharTest += new
CharEventHandler(Change_X);
3.6 構(gòu)成完整的事件處理程序?qū)嵗?
將上述步驟構(gòu)成的程序代碼組合起來(lái)就構(gòu)成一個(gè)完整的事件處理程序。
using System;
namespace ConEven1
{ //創(chuàng)建包含事件信息的類
public class CharEventArgs :EventArgs
{ public char CurrChar;//字符變量
//構(gòu)造函數(shù)
public CharEventArgs(char CurrChar)
{ this.CurrChar = CurrChar; }
class CharChecker//創(chuàng)建事件類
{ char curr_char;
//定義事件成員
public event CharEventHandler CharTest;
public char Curr_Char//事件的屬性
{ get { return curr_char; }
set
{ if (CharTest != null)
{ CharEventArgs myevent = new
CharEventArgs(value);
//調(diào)用事件處理方法 CharTest(this, myevent);
curr_char = myevent.CurrChar;
}
}
}
}
delegate void CharEventHandler
(bject sender, CharEventArgs e);
class AppEvent
{ static void Main(string[] args)
{ CharChecker chartester = new
CharChecker();//創(chuàng)建事件對(duì)象
chartester.CharTest += new
CharEventHandler(Change_X);
chartester.Curr_Char = ‘x’;
Console.WriteLine(“{0}”,
chartester.Curr_Char);
chartester.Curr_Char = ‘張’;
Console.WriteLine(“事件處理的結(jié)果:
{0}”,chartester.Curr_Char);
Console.Read();
}
static void Change_X(Object source,
CharEventArgs e)
{ if (e.CurrChar == ‘x’ ||
e.CurrChar== ‘X’)
{ Console.Write(“觸發(fā)的字符是 x ,”);
Console.Write(“把 x 替換為:”);
e.CurrChar = ‘三’;
}
else
Console.Write(“觸發(fā)的字符不是 x , ”);
}
}
}
}
上述程序的執(zhí)行結(jié)果為:
4 多播事件及其程序?qū)崿F(xiàn)
4.1 多播事件
多播代理具有創(chuàng)建方法鏈表的能力,當(dāng)調(diào)用代理時(shí),所有被鏈接的方法都會(huì)被自動(dòng)調(diào)用,也就是多播可以在一次代理調(diào)用中調(diào)用方法鏈上的所有方法。創(chuàng)建多播調(diào)用鏈表的方法是:先實(shí)例化一個(gè)代理,然后使用“+=”運(yùn)算符把方法添加到調(diào)用鏈表中;也可以使用“-=”運(yùn)算符從調(diào)用鏈表中刪除一個(gè)方法。
事件也可以多播,這一特性可以使多個(gè)對(duì)象響應(yīng)事件信息,還可以通過(guò)多點(diǎn)傳送為一個(gè)事件指定多個(gè)事件處理方法,加入其它事件處理程序或刪除其它處理程序和多重代理方法相同。
4.2 多播事件處理程序的實(shí)現(xiàn)實(shí)例
using System;
namespace ConEven2
{//定義事件信息類
public class CharEventArgs : EventArgs{ public char CurrChar;
//構(gòu)造方法
public CharEventArgs(char CurrChar)
{ this.CurrChar = CurrChar; }
}
class CharChecker//定義事件類
{ char curr_char;
//定義CharEventHandler事件成員CharTest
public event CharEventHandler CharTest;
//觸發(fā)事件的屬性
public char Curr_Char
{ get{ return curr_char; }
set{ if (CharTest != null)
{ CharEventArgs args=new
CharEventArgs(value);
//調(diào)用事件代理
CharTest(this, args);
curr_char = args.CurrChar;
}
}
}
}
//創(chuàng)建一個(gè)事件代理
delegate void CharEventHandler
(Object sender, CharEventArgs e);
class AppEvent
{ static void Main()
{ CharChecker chartester=new
CharChecker();//創(chuàng)建對(duì)象
chartester.CharTest+=new
CharEventHandler(Change_X);//關(guān)聯(lián)
chartester.CharTest+=new
CharEventHandler(Change_Y);//關(guān)聯(lián)
chartester.Curr_Char = ‘x’;
Console.WriteLine(“把x替換為:
{0}”,chartester.Curr_Char);
chartester.Curr_Char = ‘乙’;
Console.WriteLine(“事件處理的結(jié)果
:{0}”, chartester.Curr_Char);
chartester.Curr_Char = ‘y’;
Console.WriteLine(“把y替換為:
{0}”, chartester.Curr_Char);
Console.Read();
}
static void Change_X(Object source,
CharEventArgs e)
{ if (e.CurrChar==‘x’||e.CurrChar==‘X’)
{ Console.Write(“觸發(fā)的字符是x ,”);
e.CurrChar = ‘?’;
}
else
Console.Write(“觸發(fā)的字符不是 x , ”);
}
static void Change_Y(Object source,
CharEventArgs e)
{ if(e.CurrChar==‘y’|| e.CurrChar== ‘Y’)
{ Console.WriteLine(“觸發(fā)的字符是 y ”);
e.CurrChar = ‘#’;
}
else
Console.WriteLine(“觸發(fā)字符不是 y ”);
}
}
}
上述程序的執(zhí)行結(jié)果為:
5 結(jié)束語(yǔ)
其實(shí),C#系統(tǒng)將事件視作一個(gè)代理類,并根據(jù)系統(tǒng)提供的各種狀態(tài)自動(dòng)實(shí)現(xiàn)跟蹤和處理。當(dāng)對(duì)象的某個(gè)狀態(tài)發(fā)生了變化,代理就會(huì)自動(dòng)調(diào)用,并執(zhí)行代理的方法。事件和代理一樣也支持多播,一個(gè)事件發(fā)送者可以同時(shí)觸發(fā)多個(gè)處理事件的方法。
參考文獻(xiàn)
[1]劉瑞新主編. C#網(wǎng)絡(luò)編程及應(yīng)用[M]. 北京: 機(jī)械工業(yè)出版社, 2005.
[2]謝桂華, 魏亮等.Visual C#高級(jí)編程范例[M]. 北京: 清華大學(xué)出版社, 2004.
[3]邵鵬鳴編著. Visual C#程序設(shè)計(jì)基礎(chǔ)教程[M]. 北京: 清華大學(xué)出版社, 2005.
[4]唐大仕編著. C#程序設(shè)計(jì)教程[M]. 北京: 清華大學(xué)出版社, 2003.
相關(guān)熱詞搜索:探討 編程 事件 事件及其編程方法探討 事件驅(qū)動(dòng)編程 事件驅(qū)動(dòng)編程 python
熱點(diǎn)文章閱讀