事件学习.docx

上传人:b****6 文档编号:4329428 上传时间:2022-11-29 格式:DOCX 页数:10 大小:22.07KB
下载 相关 举报
事件学习.docx_第1页
第1页 / 共10页
事件学习.docx_第2页
第2页 / 共10页
事件学习.docx_第3页
第3页 / 共10页
事件学习.docx_第4页
第4页 / 共10页
事件学习.docx_第5页
第5页 / 共10页
点击查看更多>>
下载资源
资源描述

事件学习.docx

《事件学习.docx》由会员分享,可在线阅读,更多相关《事件学习.docx(10页珍藏版)》请在冰豆网上搜索。

事件学习.docx

事件学习

1、声明一个代理。

(代理可以处理某种参数类型并返回结果的一类方法,比如代理输入两个int型数据返回int型数据)

2、利用代理声明一个事件。

(具体某一种事件)

3、定义一个方法调用事件。

(怎么触发事件)

4、创建一个处理事件的方法。

(事件触发后执行声明代码)

5、将处理事件的方法和事件关联。

(多重关联/注册事件处理函数)

事件:

自定义事件与控件的事件。

微软帮我们做了一部分工作,使得我们把注意力集中到事件执行方法的设计和编码上。

初学者弄懂执行原理才有助于提高编程能力。

①、声明事件委托:

delegateC

②、声明事件Event:

A.event

③、声明事件响应函数:

B.fuction

④、关联事件和响应函数:

A.event+=C(B.fuction);

⑤、创建并调用触发方法:

A触发,B处理

区别消息和事件:

架构:

namespaceA

{

publicdelegateintMydelegate(inta,intb);

classAdd

{

publicEventMydelegatemyEvent;

publicvoidfunction(inta,intb)

{

if(myEvent!

=null)

{

myEvent(a,b);

}

}

}

classApp

{

privatestiaticvoidOnfunction(inta,intb)

{

//Dosomething();

}

}

classmain()

{

Addadd=newApp();

Add.myEvent+=newMydelegate(App.Onfuction);

add.function(1,2);

}

}

完整实例:

包括自定义事件和系统自带事件。

usingSystem;

usingSystem.Collections.Generic;

usingSystem.Linq;

usingSystem.Text;

usingSystem.Timers;

//usingSystem.Timers;

namespaceEventTest

{

//定¨义?

一?

个?

委ˉ托狣MessageHandler,?

可é以?

看′作痢?

是?

一?

个?

类え?

publicdelegatevoidMessageHandler(stringmessageText);

classConnections

{

 

//定¨义?

一?

个?

事?

件tMessageArrive,?

是?

委ˉ托狣的?

实害?

publiceventMessageHandlerMessageArrive;

privateTimerpollTimer;

privatestaticRandomrandom=newRandom();

publicConnections()

{

this.pollTimer=newTimer();

//系μ统?

内ú部?

阰publicdelegatevoidElapsedEventHandler(objectsender,ElapsedEventArgse);

//系μ统?

内ú部?

阰publiceventElapsedEventHandlerElapsed;说μ明÷已?

经-帮?

我ò们?

做?

好?

了?

定¨义?

委ˉ托狣和í定¨义?

事?

件t两?

个?

步?

骤è

pollTimer.Elapsed+=newElapsedEventHandler(Display);

}

publicvoidConnect()

{

pollTimer.Start();

}

publicvoidDisconnect()

{

pollTimer.Stop();

}

publicvoidDisplay(objectsource,ElapsedEventArgse)

{

Console.WriteLine("NewMessageComing");

if(random.Next(9)==0&&MessageArrive!

=null)

{

//触洌?

发ぁ镸essageArrive事?

件t

MessageArrive("NewMessageArrived,Andhasbeenhandledsuccessfully");

}

}

staticvoidMain(string[]args)

{

Connectionsconnector=newConnections();

Displaydisplayor=newDisplay();

//将?

一?

个?

委ˉ托狣实害?

例赋3值μ给?

事?

件tMessageArrive,?

参?

数簓为a方?

法ぁisplayMessage,方?

法ぁ?

的?

参?

数簓要癮与?

委ˉ托狣类え?

的?

参?

数簓一?

致?

connector.MessageArrive+=newMessageHandler(displayor.DisplayMessage);

connector.Connect();

Console.ReadKey();

}

}

 

publicclassDisplay

{

publicvoidDisplayMessage(stringtext)

{

Console.WriteLine(text);

}

}

}

MSDN的解释:

类或对象可以通过事件向其他类或对象通知发生的相关事情。

发送(或引发)事件的类称为“发行者”,接收(或处理)事件的类称为“订户”。

在典型的C#Windows窗体或Web应用程序中,可订阅由控件(如按钮和列表框)引发的事件。

可使用VisualC#集成开发环境(IDE)来浏览控件发布的事件,选择要处理的事件。

IDE会自动添加空事件处理程序方法和订阅事件的代码。

有关更多信息,请参见如何:

订阅和取消订阅事件(C#编程指南)。

事件概述

--------------------------------------------------------------------------------

事件具有以下特点:

发行者确定何时引发事件,订户确定执行何种操作来响应该事件。

一个事件可以有多个订户。

一个订户可处理来自多个发行者的多个事件。

没有订户的事件永远也不会引发。

事件通常用于通知用户操作,例如,图形用户界面中的按钮单击或菜单选择操作。

如果一个事件有多个订户,当引发该事件时,会同步调用多个事件处理程序。

要异步调用事件,请参见使用异步方式调用同步方法。

在.NETFramework类库中,事件是基于EventHandler委托和EventArgs基类的。

http:

//127.0.0.1:

47873/help/2-19700/ms.help?

product=VS&productVersion=100&method=f1&query=System.EventHandler`1%00EventHandler&locale=zh-CN&category=DevLang%3acsharp%00TargetFrameworkMoniker%3a.NETFramework,Version%3Dv4.0

泛型委托:

程序源码就是使用这种。

//ThisexampledemonstratestheEventHandlerdelegate.usingSystem;usingSystem.Collections.Generic;//---------------------------------------------------------publicclassMyEventArgs:

EventArgs{privatestringmsg;publicMyEventArgs(stringmessageData){msg=messageData;}publicstringMessage{get{returnmsg;}set{msg=value;}}}//---------------------------------------------------------publicclassHasEvent{//DeclareaneventofdelegatetypeEventHandlerof//MyEventArgs.publiceventEventHandlerSampleEvent;publicvoidDemoEvent(stringval){//Copytoatemporaryvariabletobethread-safe.EventHandlertemp=SampleEvent;if(temp!

=null)temp(this,newMyEventArgs(val));}}//---------------------------------------------------------publicclassSample{publicstaticvoidMain(){HasEventhe=newHasEvent();he.SampleEvent+=newEventHandler(SampleEventHandler);he.DemoEvent("Heythere,Bruce!

");he.DemoEvent("Howareyoutoday?

");he.DemoEvent("I'mprettygood.");he.DemoEvent("Thanksforasking!

");}privatestaticvoidSampleEventHandler(objectsrc,MyEventArgsmea){Console.WriteLine(mea.Message);}}//---------------------------------------------------------/*Thisexampleproducesthefollowingresults:

Heythere,Bruce!

Howareyoutoday?

I'mprettygood.Thanksforasking!

*/

当然你调用它之前还得先绑定一个函数给它,不然会出错的.所以一般用if(onSayHello!

=null)这样判断一下,如果事件还没绑定啥函数上去就为null

那既然事件都跟调用函数都差不多了,还不如直接调用函数或者调用代理,为啥搞得多此一举,再整个事件来啊.

用自定义事件可能基于两种原因吧,当然这是我自己瞎猜的啊

一,是体现一种设计模式,订阅者模式.

二,是当体现封装原则.

比如一个class想调用另外一个class中某个函数时,不想让直接调用,或者函数声明为private的,就可通过event间接的调用.因为delegate相当于指向函数的指针,而event又相当于是对delegate的封装.那你可能又问封装有啥好的啊,这可能是体现一种设计思想,对以后扩充功能或做一些额外的处理有用吧.不然像像我们把所以类中的字段都给封装成一个个的属性(property),大部分时候是一点都看不出来有啥用,反而觉得有点多此一举,还不如直接用字段别用属性呢.但如果我们有时想在属性中做些额外的处理时特别有用.比如只让你读取字段值不让赋值,或者反过来.

举个用自定义事件调用其他类中的private函数的简单例子吧.

在classA中有private的函数sayHello.那classB中肯定不能直接调用sayHello了.当然我们另外还要假设在A中用到了B.

delegatevoidDelegateSayHello(stringname);//在类外面某个地方,它其实也可以看成一种特殊的类了.当然也可以放在某个类里面定义

C#委托与事件的本质区别

从定义上说,委托被编译器编译成一个类,所以它可以像类一样在任何地方定义,而事件被编译成一个委托类型的私有字段和两个公有add和remove方法(有点类似于属性的定义)不过这两个方法都有一个参数,这个参数就是委托,所以,它只能定义在一个类里面。

从定义可知,委托是要是需要实例化的,它4个方法:

一个构造器,Invoke,BeginInvoke和EndInvoke。

构造器有两个参数分别是:

一个对象引用,另一个是引用回调方法的一个IntPtr。

然而实例化委托的代码的参数只是一个方法的引用。

但这不是问题,编译器明白这其中的一切会获取对应的参数。

然而事件是不需要实例化的因为他只是一个字段和两个方法,只是类的一些成员,但是可以初始化,通过一些赋值操作!

实例化委托时,定义他参数的方法的参数及返回类型必须符合委托的Invoke参数及返回类型,而事件被定义后,它可以通过方法所在类的对象调用add方法来添加一个委托和remove方法来移除一个委托!

而两个方法的结果是返回一个委托引用并赋值给事件定义生成的私有委托字段,如果是多次调用就返回一个委托列表头的引用。

而传入的这个参数即是由要触发的方法而封装的委托。

(参数为什么是委托而不直接传入一个方法引用呢,这样效率不是更高吗)因为委托是调用回调方法的一种类型安全的方式。

通过add方法即是订阅了一个事件,然后就是触发事件了,即通过点击按钮等输入操作即可触发事件,然后调用私有的委托变量,然后即像调用委托一样,调用他的Invoke方法即引用定义的方法的地址来执行该方法,然后这个事件就结束了。

总结:

事件的订阅分两个阶段:

首先是传入的参数(即委托)的实例化,相当于委托的实例化,调用该委托的构造函数(一个对象引用,一个IntPtr类型的回调方法的引用),其次就是委托链(也即多播委托)的构建过程,第一次订阅是用一个null和传入的委托的Combine,此时直接返回传入的委托地址,如果第二次订阅就会构造一个新的委托对象,_invocationList字段被初始化为一个委托对象数组,引用两个委托地址,最后返回这个新建的对象地址,以后依此类推。

接下来就是事件的触发阶段了,通过鼠标单击或动态用代码去实现,其本质只有一个步骤即委托的调用,如果只有一个委托,直接调用Invoke方法,如果有多个委托,即发现_invocationList不为null,会循环调用数组里的所有元素,每个元素的实现即为只有一个委托时调用的Invoke方法。

简而言之,即事件分为两个阶段一个是委托的实例化(对应事件订阅),一个是委托的调用(对应事件触发)。

加On是命名规范。

通常C#自定义事件有下面的几个步骤:

1、声明一个delegate:

(用于事件的类型的定义)

如:

1.publicdelegatevoid事件名称EventHandler(objectserder,EventArgse);

//事件名称用你的自己的来代替,随后的EventHandler是C#的建议命名规范,当然如果你不想遵守,可以使用任何字符甚至可以不要。

如果你想自定义事件的参数EventArgs,你可以从这个类派生你自己的事件参数类,然后在delegate的声明中,用你的参数类替换EventArgs

注:

要全面了解自定义事件的原理,你需要学习有关delegate的知识。

2、在你的类中声明一个事件,并且使用步骤1的delegate作为事件的类型:

1.publicevent事件名称EventHandler事件名称;

3、在你的类中需要触发事件的方法中,添加事件触发代码:

1.事件名称(this,newEventArgs());

或者:

1.if(事件名称!

=null)

2.事件名称(this,newEventArgs());

//如果使用你自己的事件参数类,你可以用你的参数类事例替换newEventArgs(),同时在你的参数类中保存你需要传递的数据。

4、C#自定义事件注册:

事件注册和普通的事件注册没有不同,也就是说如果一个外部的对象在你的事件被触发的时候需要作出响应,那么你可以在外部了构造器中(或者适当的地方)对事件进行注册

1.带有事件的类实例.事件名称+=new事件名称EventHandler(事件处理方法名称);

5、编写事件处理方法:

1.publicvoid事件处理方法名称(objectsender,EventArgse)

2.{

3.//添加你的代码

4.}

注:

如果你在类中处理自己的触发事件,你可以选择C#自定义事件步骤4和5的方式,也就是注册自己,也可以在触发事件代码中直接调用事件处理方法。

【编辑推荐】

1.C#自定义控件的开发:

Pin和Connector

2.比较C#自定义控件的property(属性)和/attribute(性质)

3.C#组件开发:

COM和.NET对象之间的互操作

4.介绍.NET平台、C#和ASP.NET

5.C#Attributes:

定义设计期信息

追踪告警事件:

●事件绑定:

m_BatteryRtMemory.OnOccurWarning1+=newEventHandler(m_BatteryRtMemory_OnOccurWarning1);

事件:

m_BatteryRtMemory.OnOccurWarning1

●事件定义:

publiceventEventHandlerOnOccurWarning1;

委托:

EventHandler

●委托定义:

publicdelegatevoidEventHandler(objectsender,TEventArgse);

响应事件方法:

m_BatteryRtMemory_OnOccurWarning1

●响应事件方法定义:

voidm_BatteryRtMemory_OnOccurWarning1(objectsender,ReceiveWarningEvente)

{

if(e.ReceiveXEventList==null||e.ReceiveXEventList.Count<=0)

return;

foreach(ReceiveXEventwarning1Eventine.ReceiveXEventList)

{

StringcabinetUnitFormatter=AppCommonTools.FormatUnit(warning1Event.CabinetNo,warning1Event.SideNo,warning1Event.UnitNo);

Stringtips=GetWarning1Desc(cabinetUnitFormatter,warning1Event.Flag);

warningFrm.LogMessage(tips,WaringType.WarningTips);

m_Logger.Info(tips);

}

}

●触发(直接代码触发):

if(OnOccurWarning1!

=null&&warningEvent1.ReceiveXEventList.Count>0)

{

OnOccurWarning1(this,warningEvent1);

}

也就是说:

运行过事件绑定多后OnOccurWarning1就不为空。

当UpdateData被调用的时候,只要ReceiveXEventList.Count的大小大于0,那么就会响应事件,就好像点击了一个按钮一样。

通过委托找到绑定的方法,执行:

m_BatteryRtMemory_OnOccurWarning1(),这个方法做了两件事情,①、在主界面的告警框里写入记录(有多少告警数量就写入多少条),还写了次日志文件。

整个事件完成后继续执行告警类型2等等。

但是为什么要提供几种类型的告警信息响应事件呢?

其实一个事件也可以完成,但是鉴于告警类型种类很多,如果写在同一个方法里面就会使得方法很臃肿,不便于管理和阅读(可读性和可维护性都比较差)。

关于委托的继承问题:

EventHandler

其中:

publicclassReceiveWarningEvent:

ReceiveWorkStepEvent

publicclassReceiveWorkStepEvent:

EventArgs

追踪实时内存库化成结束事件:

●事件绑定:

m_BatteryRtMemory.OnHcFinished+=newEventHandler(m_BatteryRtMemory_OnHcFinished_PH);//鹏?

辉?

使?

用?

通过配置文件来开启是否执行这个事件。

●事件定义:

publiceventEventHandlerOnHcFinished;

定义在主界面里面。

●委托定义:

publicdelegatevoidEventHandler(objectsender,TEventArgse);

继承自:

EventArgs,新增了自己的属性和构造函数。

●触发(直接线程里面调用的):

if(OnHcFinished!

=null)

OnHcFinished(this,newHcFinishedEvent(rtData.CabinetNo,rtData.SideNo,rtData.UnitNo,stepFlowId));

响应函数:

privatevoidm_BatteryRtMemory_OnHcFinished_PH(objectsender,HcFinishedEvente)

主界面的函数。

动态生成单选框:

绑定了方法:

rb_CheckedChanged。

跟界面上直接存在着单选框也有点区别。

实际上是一样的,表现形式不一样而已。

RadioButtonrb=newRadioButton();

rb.Parent=panelCabinet;

rb.Name=info.cabinet_no.ToString();

rb.Text=info.cabinet_name;

rb.Location=newPoint(panelCabinet.Width/m_AllCabinetInfoList.Count*i,1);

rb.Tag=info;

rb.AutoSize=true;

rb.CheckedChanged+=newEv

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学 > 天文地理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1