.NET框架下C#语言的事件处理

转载 2004年09月01日 12:15:00
简介
任何编写过图形用户界面(GUI)软件的开发人员都熟悉事件处理编程,当用户与GUI控制进行交互时(例如点击表格上的按钮),作为上述事件的反应,就会执行一个或多个方法。没有用户的参与,事件也可能执行。事件处理程序是对象的方法,是根据应用程序中发生的事件而执行的。为了理解.Net框架下的事件处理模式,我们需要理解代理的概念。
C#中的代理
C#中的代理允许我们将一个类中的方法传递给其他类的对象。我们能够将类A中的方法m封装为一个代理,传递给类B,类B能够调用类A中的方法m,静态和实例方法都可以传送。C++软件开发人员应该对这一概念非常熟悉,在C++中,开发人员能够以参数的形式使用函数指针将函数传递给同理个类或其他类中的方法。代理的概念是在Visulal J++中引入的,然后又被带到了C#中。在.Net框架中C#的代理是以从System.Delegate中继承的类的形式实现的。使用代理需要4个步骤:
1、定义一个输入参数与要进行封装的方法完全相同的代理对象。
2、定义所有输入参数与在第1步中定义的代理对象相同的方法。
3、创建代理对象,并与希望封装的方法进行连接。
4、通过代理对象调用封装的方法。
下面的C#代码通过实现一个代理、4个类举例说明了上面的4个步骤:
using System;
//步骤1:定义一个具有被封装方法输入参数的代理对象
public delegate void MyDelegate(string input);
//步骤2:定义与定义的代理对象具有相同输入参数的方法
class MyClass1{
public void delegateMethod1(string input){
Console.WriteLine("This is delegateMethod1 and the input to the method is {0}",input);
}
public void delegateMethod2(string input){
Console.WriteLine("This is delegateMethod2 and the input to the method is {0}",input);
}
}
//步骤3:创建代理对象,插入方法
class MyClass2{
public MyDelegate createDelegate(){
MyClass1 c2=new MyClass1();
MyDelegate d1 = new MyDelegate(c2.delegateMethod1);
MyDelegate d2 = new MyDelegate(c2.delegateMethod2);
MyDelegate d3 = d1 + d2;
return d3;
}
}
//步骤4:通过代理调用被封装的方法。
class MyClass3{
public void callDelegate(MyDelegate d,string input){
d(input);
}
}
class Driver{
static void Main(string[] args){
MyClass2 c2 = new MyClass2();
MyDelegate d = c2.createDelegate();
MyClass3 c3 = new MyClass3();
c3.callDelegate(d,"Calling the delegate");
}
}

C#中的事件处理程序
C#中的事件处理程序是一个带有特定输入参数的代理,如下所示:
public delegate void MyEventHandler(object sender, MyEventArgs e);

上面定义中的第一个参数(sender)指定了发生事件的对象,第二个参数(e)存储着在事件处理程序中要用到的数据。MyEventArgs类是继承EventArgs类得来的,EventArgs类是MouseEventArgs、ListChangedEventArgs等更专业化的类的基础类。对于GUI事件,我们可以使用这些特定的EventArgs类的对象,而无需自己创建特定的EventArgs类。然而,对于非GUI事件而言,我们仍然需要创建自己的特定的EventArgs类,存储希望向代理对象传递的数据。我们可以通过继承EventArgs类创建自己特定的EventArgs类:
public class MyEventArgs EventArgs{
public string m_myEventArgumentdata;
}
在事件处理程序中,代理对象的调用需要用到event关健字,如下所示:
public event MyEventHandler MyEvent;
下面我们将建立二个类,体会.Net框架中事件处理机制的工作原理。在对代理的讨论的第二个步骤中,要求我们定义与定义的代理有完全相同的输入参数的方法。在我们的例子中,类A将提供事件处理程序(与代理对象具有相同输入参数的方法。),它将创建代理对象(对代理讨论中的第三步)并安装事件处理程序。类A然后会将代理对象传递给类B。当类B中有事件出现时,它就会执行类A中的事件处理程序方法。
using System;
//步骤1:创建代理对象
public delegate void MyHandler1(object sender,MyEventArgs e);
public delegate void MyHandler2(object sender,MyEventArgs e);
//步骤2:创建事件处理程序方法
class A{
public const string m_id="Class A";
public void OnHandler1(object sender,MyEventArgs e){
Console.WriteLine("I am in OnHandler1 and MyEventArgs is {0}", e.m_id);
}
public void OnHandler2(object sender,MyEventArgs e){
Console.WriteLine("I am in OnHandler2 and MyEventArgs is {0}", e.m_id);
}
//步骤3:创建代理,安装事件处理程序,并向启动事件的对象注册。
public A(B b){
MyHandler1 d1=new MyHandler1(OnHandler1);
MyHandler2 d2=new MyHandler2(OnHandler2);
b.Event1 +=d1;
b.Event2 +=d2;
}
}
//步骤4:通过代理调用封装的方法。
class B{
public event MyHandler1 Event1;
public event MyHandler2 Event2;
public void FireEvent1(MyEventArgs e){
if(Event1 != null){
Event1(this,e);
}
}
public void FireEvent2(MyEventArgs e){
if(Event2 != null){
Event2(this,e);
}
}
}
public class MyEventArgs EventArgs{
public string m_id;
}
public class Driver{
public static void Main(){
B b= new B();
A a= new A(b);
MyEventArgs e1=new MyEventArgs();
MyEventArgs e2=new MyEventArgs();
e1.m_id ="Event args for event 1";
e2.m_id ="Event args for event 2";
b.FireEvent1(e1);
b.FireEvent2(e2);
}
}

C#中的GUI事件处理
Windows Forms(支持GUI应用程序的.NET框架)中的事件处理使用.NET事件处理模式。我们下面将应用这种模式编写一个简单的应用程序,该应用程序有一个继承自System.Windows.Forms.Form类的MyForm类。如果仔细地研究一下代码和其中的三行注释,就会发现其实我们无须定义代理和使用event关健字调用这些代理,因为我们已经可以使用GUI控制(表格、按钮等)的事件(鼠标点击等),代理就是System.EventHandler。当然了,我们仍然需要定义方法,创建代理对象(System.EventHandler),并在代理对象中安装方法,一旦有事件发生,方法就会开始执行。
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

public class MyForm Form{
private Button m_nameButton;
private Button m_clearButton;
private Label m_nameLabel;

private Container m_components = null;

public MyForm(){
initializeComponents();
}
private void initializeComponents(){
m_nameLabel=new Label();
m_nameButton = new Button();
m_clearButton = new Button();

SuspendLayout();

m_nameLabel.Location=new Point(16,16);
m_nameLabel.Text="Click NAME button, please";
m_nameLabel.Size=new Size(300,23);

m_nameButton.Location=new Point(16,120);
m_nameButton.Size=new Size(176, 23);
m_nameButton.Text="NAME";
//创建代理,并安装方法,将代理捆绑在按钮的Click事件上
m_nameButton.Click += new System.EventHandler(NameButtonClicked);

m_clearButton.Location=new Point(16,152);
m_clearButton.Size=new Size(176,23);
m_clearButton.Text="CLEAR";
//创建代理,并安装方法,将代理捆绑在按钮的Click事件上
m_clearButton.Click += new System.EventHandler(ClearButtonClicked);

this.ClientSize = new Size(292, 271);
this.Controls.AddRange(new Control[] {m_nameLabel,m_nameButton,m_clearButton});
this.ResumeLayout(false);
}
//定义输入参数与代理完全相同的方法
private void NameButtonClicked(object sender, EventArgs e){
m_nameLabel.Text="My name is john, please click CLEAR button to clear it";
}
private void ClearButtonClicked(object sender,EventArgs e){
m_nameLabel.Text="Click NAME button, please";
}
public static void Main(){
Application.Run(new MyForm());
}
}

结束语
Java和Smalltalk等其他的面向对象的编程语言中都没有代理的概念,这一概念是在C#中新引进的,它源自于C++和J++。我希望上面的讨论使第一次使用面向对象的编程语言时就使用C#语言的编程人员能够弄明白代理的概念。如果使用Visual Studio IDE作为C# GUI的开发环境,无需编写代码就能够将代理中的方法与由GUI控制生成的事件(例如用鼠标点击按钮等)连接在一起,当然了,我们还是应当知道这是怎么回事。

终于掌握了最基本的socket通信在.net框架下用c#语言

哈哈,努力了有10天吧。从开始学C#的语法,再学计算机网络的基本原理,然后去看别人c# socket 编程的例子。理解了,自己能写出了,完全是自己写出的。还是很有感觉的。...
  • CGGUANG
  • CGGUANG
  • 2016年11月21日 00:02
  • 1773

C#.NET 消息机制

http://blog.csdn.net/fan158/article/details/6178392 一、消息概述       众人周知,window系统是一个消息驱动的系统, ...
  • conganguo
  • conganguo
  • 2016年05月23日 17:18
  • 464

[C#]委托和事件(详细讲解)

引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易。它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没...
  • s10141303
  • s10141303
  • 2014年03月02日 00:23
  • 4139

C# 中的委托和事件(详解)

C# 中的委托和事件(详解) 转载:http://www.cnblogs.com/SkySoot/archive/2012/04/05/2433639.html C# 中的委托和事件 ...
  • beyonddeg
  • beyonddeg
  • 2016年12月09日 00:48
  • 1125

Spring MVC防御CSRF、XSS和SQL注入攻击 - Mainz - 博客园

Spring MVC防御CSRF、XSS和SQL注入攻击 - Mainz - 博客园 本文说一下SpringMVC如何防御CSRF(Cross-site request forgery跨站请求伪...
  • wscrf
  • wscrf
  • 2017年05月23日 10:37
  • 869

在C#中处理事件

 C#中的事件处理实际上是一种具有特殊签名的delegate,象下面这个样子: public delegate void MyEventHandler(object sender, M...
  • Andrewniu
  • Andrewniu
  • 2016年06月30日 16:45
  • 407

最全的C#图片处理类ImageHelper.cs

【图片处理】最全的C#图片处理类ImageHelper.cs http://bbs.cskin.net/forum.php?mod=viewthread&tid=113&fromuid=2446 ...
  • liwb1987
  • liwb1987
  • 2015年04月21日 14:48
  • 3879

C#中的委托和事件

C#中的委托和事件   前言   委托和事件在.NET框架中应用的很广泛,但是楼主因为知识尚浅,用到的不多,但是听前辈们说,这个委托和事件就像两座大山,只要翻过了这...
  • shanyongxu
  • shanyongxu
  • 2016年02月25日 17:09
  • 1102

Struts2学习(第七篇)——数据类型转换详解

本文来自:曹胜欢博客专栏。转载请注明出处:http://blog.csdn.net/csh624366188            Web应用程序的交互都是建立在HTTP之上的,互相传递的...
  • tangxiong2510
  • tangxiong2510
  • 2014年03月31日 21:49
  • 489

.NET中常见的内存泄露问题——GC、委托事件和弱引用

其实吧,内存泄露一直是个令人头疼的问题,在带有GC的语言中这个情况得到了很大的好转,但是仍然可能会有问题。 一、什么是内存泄露(memory leak)? 内存泄露不是指内存坏了,也不是指...
  • Linux7985
  • Linux7985
  • 2015年03月05日 11:00
  • 2205
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:.NET框架下C#语言的事件处理
举报原因:
原因补充:

(最多只允许输入30个字)