




已阅读5页,还剩3页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C#事件及响应方法让你明白private void button1_Click(object sender, System.EventArgs e) C#语言自C/C+演变而来。它是现代、简单、完全面向对象和类型安全的。C#语言是微软公司针对.Net平台才推出来的一门新语言,作为.Net平台的第一语言,它几乎集中了所有关于软件开发和软件工程研究的最新成果。 面向对象、类型安全、组件技术、自动内存管理、跨平台异常处理、版本控制、代码安全管理在.NET应用程序开发中,不管是WEB Forms(ASP.NET)还是Windows Forms,都涉及到大量对象的事件响应及处理,比如客户在线提交一份订单、或是在Windows窗口上移动鼠标等都将有事件发生。那么在C#中,是怎样声明事件并为事件添加响应方法的呢?下面的文章对此为大家作了详细的讲述。原理简介 在C#中,一个类可以有域(Fields)、属性(Properties)、方法(Methods)、索引(Indexs)、事件(Events)等成员,其中事件(Events)成员就是用来声明一个类事件的。在类中声明一个事件成员一般采用如下的语法形式: public event 代表名 事件名。 如在Control类中声明了一个Click事件成员,其语法如下: public event EventHandler Click; 在C#中,增加了一个新的数据类型delegate(代表)来解决事件处理问题。代表数据类型非常类似于C语言中的指针,其与指针不同的是,其是代码是安全的,可管理的。由于C#本身的简易性,对于没有使用过及指针的程序来说,理解delegate也是非常容易的。 在C#中,通过使用delegate,你可以通过“+=”(加等于)操作符非常容易地为.Net对象中的一个事件添加一个甚至多个响应方法;还可以通过非常简单的“-=”(减等于)操作符取消这些响应方法。如下面为temp按钮添加Click事件的语句: temp.Click+=new System.EventHandler(this.Test);/为test添加事件处理方法 在上面声明事件的语句中,Eventhandler是一个delegate(代表)类型,其在.Net类库中如下声明的: public delegate void EventHandler(object sender,EventArgs e); 这样,所有形如:void 函娄名(object 参数名,EventArgs 参数名);的函数都可以作为Control类的Click事件响应方法了。如下面所定义的一个事件响应方法: private void button1_Click(object sender, System.EventArgs e) 由于是通过delegate(代表类型)来处理事件,因此,可能通过累加使一个事件具有多个响应方法;与此同时,还可以使一个方法作为多个事件的响应方法。(注意:在C#语言类中的event成员后面只能出现“+=”与“-=”两个表示添加与取消事件响应函数的操作符。) 不管是ASP.Net还是一般的Windows Forms 编程,在C#中,基本上我们遇到的事件响应方法都是说明成如下的形式: private void button1_Click(object sender, System.EventArgs e) 那么,一个事件响应方法的存取权限、返回值类型、参数及类型甚至方法名称等是否都必须固定不变呢?答案是:不是!一般情况下,事件的响应方法中都有两个参数,其中一个代表引发事件的对象即sender,由于引发事件的对象不可预知的,因此我们把其声明成为object类型,所有的对象都适用。第二个参数代表引发事件的具体信息,各种类型的事件中可能不同,这要根据类中事件成员的说明决定。 我们知道,事件是通过delegate(代表) 来处理的。假设将要表示事件的代表说明成如下形式: delegate int MyEventHandler(object sender, ToolBarButtonClickEventArgs e); 则当涉及上面的事件响应函数声明时,就须要声明成如下的形式: private int MyTest(object sender,ToolBarButtonClickEventArgs e) 在给对象添加事件响应方法时就可以用如下的代码实现: Control.Event+=new MyEventHandler(MyTest); 示例程序 下面,我们用Visual Studio .Net开发工具设计了一个简单Windows Forms的程序,向大家展示了C#中具体是怎样实现事件响应处理的。 *主要类 System.Windows.Forms.Application类:应用程序类。 System.Windows.Forms.Form类:窗体类。 System.Windows.Forms.Label类:文字标签类,主要用于在窗口上添加标签信息。 System.Windows.Forms.Button类:按钮类,生成一个命令按。 System.EventHandler Delegate(代表):其是.Net类库中的一个公用代表类型,主要用于说明并初始化一个事件方法,该代表具有两个参数object sender表示引发事件的对象,System.EventArgs e 代表事件的相应信息,如鼠标的x,y值等。 * 设计简介 在Visual Studio.Net选择新建Windows 应用程序,选择程序地址并输入程序名后,将生成一个非常简单的初始化窗体Form1类;在初始窗体中添加一个标签(Label)及一个按钮(Button)并设置相应的位置大小及属性值等。 双击按钮进入代码编辑区,此时系统自动生了一个用于处理按钮Click事件的方法,即button1_Click()。在方法中添如下的代码: Button temp=new Button(); temp.Text=新增加的按钮; temp.Location=new Point(30,80); temp.Click+=new EventHandler(this.Test); this.Controls.Add(temp); label1.Click+=new EventHandler(this.Test); 完成后,为窗体Form1类添加一个响应事件的方法Test(),如下: private void Test(object sender,System.EventArgs e) MessageBox.Show(这是我自定义的事件响应函数!,提示信息); 完成代码后保存,编译运行即可以看程序中各控件的事件响应情况. * 运行效果 程序运行开始时有一个标签及一个按钮,此时点击标签没有任何响应信息,然后点击“为控件添加事件”按钮,将在窗体中增加一个显示为“新增加的按钮”的按钮,此时再点击标签将会看到有响应信息,即弹出一个对话框说明事作已经得到处理。点击一下“新增加的按钮”也将看到有事件响应信息。 再点击“为事件添加按钮”此时添体界面看到不变,其实已经有两个显示为“新增加的按钮”的按钮在窗体上,只是因为重复显示在同一位置看不到而已。非常有趣的是,再点击标签试一下,我们会发现事件响应方法被执行了两次。 * 关键代码及注释 下面我们列出了本程序中比较核心的代码,并作了详细的注释,请大家仔细体会。 privatevoidInitializeComponent()/窗体构造函数调用的窗体初始化函数,主要由VisualStudio.Net自动生成。this.button1.Click+=newSystem.EventHandler(this.button1_Click);/为button1对象的Click事件添加响应方法button1_Click()。privatevoidbutton1_Click(objectsender,System.EventArgse)/系统生成的button1按钮的Click事件响应方法。Buttontemp=newButton();/生成一个Button对象temp.Text=新增加的按钮;/设置Button对象的外观属性temp.Location=newPoint(30,80);temp.Click+=newEventHandler(this.Test);/把Test()添加新增按钮Click事件的响应方法。this.Controls.Add(temp);/把Button对象temp添加到当前窗体中label1.Click+=newEventHandler(this.Test);/把Test()也添加为标签(label1)Click事件的响应方法。注意C#中事件响应可以有多个方法或者是一个方法的重复。privatevoidTest(objectsender,System.EventArgse)/自定义事件处理函数,注意函数的参数类型。MessageBox.Show(这是我自定义的事件响应函数!,提示信息);/弹出一个对话框,显示提示信息。比如,在写这个类的时候,根本就不能确定要调用哪个对象的方法:例如,你把自己的一个对象上的方法挂在微软的button的一个事件上。微软在写button时根本就不可能知道这个事件发生时,需要调用哪个对象的哪个方法,只有你自己去指定说需要调什么方法,并且以委托的方式挂在相应的事件上。 微软在写button的事件时,唯一能确定的是这个事件的格式,或者说这个事件需要调用的方法的格式, 类似于 button1_click(object sender, EnentArgs e) 等等。 只要是按照这个类型写的方法,都能被挂在这个事件上,并且在事件发生时,方法会被调用。 而规定了事件方法格式,就确保了事件发生时被调用的方法都是合法的,不会出现方法类型不匹配等等。这就是所谓的委托是类型安全的。通俗的说就是你在写一个类的时候,这个类要完成一件事情,但是你有不知道这件事情该怎么完成,你只知道要完成这件事情,只有这个类在运行的时候调用者方知道怎么完成这件事情,这时候你用一个委托来告诉调用者,这时候要完成一件事情,至于事情怎么完成则有调用方通过委托来完成 delegate),刚开始学的时候觉得很难理解。我的理解是这样的:首先它是一个类,定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法, 同时使得程序具有更好的可扩展性。 今天看到一个朋友的解释,我感到很奇妙。所以摘录下来了: 比如说你去看电影,电影院卖给你两张票,不过在卖的时候他肯定不知道这个位置是你座还是你朋友座,是男的座还是女的座.只有等电影开场了,大家都做上去了一切就清楚.你可以将委托理解为一个占位符,就是先站一个位置.具体是什么东西等用的时候在指定. 其实这只是从一个侧面去解释了dlegate,不过很生动形象。 那既然是从一个侧面解释了, 那委托还有那些功能呢。 为什么要使用委托呢。 如很多人所想,有些地方可以直接调用对象的方法,而不用委托。 但有些时候这样做不合适。 比如,在写这个类的时候,根本就不能确定要调用哪个对象的方法:例如,你把自己的一个对象上的方法挂在微软的textbox 的一个事件上。微软在写textbox时根本就不可能知道这个事件发生时,需要调用哪个对象的哪个方法,只有你自己去指定说需要调什么方法,并且以委托的方式挂在相应的事件上。 微软在写textbox的事件时,唯一能确定的是这个事件的格式,或者说这个事件需要调用的方法的格式, 类似于 button1_click(object sender, EnentArgs e) 等等。 只要是按照这个类型写的方法,都能被挂在这个事件上,并且在事件发生时,方法会被调用。而规定了事件方法格式,就确保了事件发生时被调用的方法都是合法的,不会出现方法类型不匹配等等。这就是所谓的委托是类型安全的。而c+下面用void* 的函数指针实现事件处理缺少对函数格式的检查。 所以C# 发明了委托这个怪东西,为的就是然被调用的函数格式正确。 委托的组成部分: 委托类型的名称都应该以EventHandler结束。 委托的原型定义:有一个void返回值,并接受两个输入参数:一个Object 类型,一个 EventArgs类型(或继承自EventArgs)。 事件的命名为 委托去掉 EventHandler之后剩余的部分。 继承自EventArgs的类型应该以EventArgs结尾。 范例:(note:假设我们有个高档的热水器,我们给它通上电,当水温超过95度的时候:1、扬声器会开始发出语音,告诉你水的温度;2、液晶屏也会改变水温的显示,来提示水已经快烧开了。我们写个程序来模拟这个烧水的过程,我们将定义一个类来代表热水器,我们管它叫:Heater,它有代表水温的字段,叫做temperature;当然,还有必不可少的给水加热方法BoilWater(),一个发出语音警报的方法MakeAlert(),一个显示水温的方法,ShowMsg()。)using System;using System.Collections.Generic;using System.Text;namespace Delegate / 热水器 public class Heater private int temperature; public string type = RealFire 001; / 添加型号作为演示 public string area = China Xian; / 添加产地作为演示 /声明委托 public delegate void BoiledEventHandler(Object sender, BoiledEventArgs e); public event BoiledEventHandler Boiled; /声明事件 / 定义BoiledEventArgs类,传递给Observer所感兴趣的信息 public class BoiledEventArgs : EventArgs public readonly int temperature; public BoiledEventArgs(int temperature) this.temperature = temperature; / 可以供继承自 Heater 的类重写,以便继承类拒绝其他对象对它的监视 protected virtual void OnBoiled(BoiledEventArgs e) if (Boiled != null) / 如果有对象注册 Boiled(this, e); / 调用所有注册对象的方法 / 烧水。 public void BoilWater() for (int i = 0; i 95) /建立BoiledEventArgs 对象。 BoiledEventArgs e = new BoiledEventArgs(temperature); OnBoiled(e); / 调用 OnBolied方法 / 警报器 public class Alarm public void MakeAlert(Object sender, Heater.BoiledEventArgs e) Heater heater = (Heater)sender; /这里是不是很熟悉呢? /访问 sender 中的公共字段 Console.WriteLine(Alarm:0 -
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年消化病学手术操作规范答案及解析
- 2025年影像科肝脏超声检查的技巧与结果判断考核答案及解析
- 2025年骨科常见创伤处理技能检测答案及解析
- 2025年生殖医学生殖医学时间测验试卷答案及解析
- 2025年口腔颌面外科患者术前评估实操模拟测试卷答案及解析
- 2025年消化内镜检查操作规范性评估测试答案及解析
- 2025年护理学基础知识综合模拟考试答案及解析
- 2025年胸心脏外科学常见胸片影像解读技巧考试卷答案及解析
- 2025年心血管疾病预防和健康教育模拟考试答案及解析
- 2025年影像诊断学常见病例解读与鉴别诊断模拟考试卷答案及解析
- 拜耳法氧化铝生产工艺流程框图
- 行政主管岗位职责及工作内容
- 机关档案管理工作培训课件
- 生产安全事故应急救援演练记录
- 2023版初中化学跨学科实践活动(化学)
- 《新能源汽车驱动电机及传动技术》课程教案
- 钎焊工艺有关标准
- 九年级初三英语七选五专练1(10篇带答案)-
- 委托加工协议(简易版)
- 高校电子课件:金融风险管理(第五版)
- 会议组织与服务完整版教学课件全书电子讲义(最新)
评论
0/150
提交评论