C#事件(event)使用方法详解

 更新时间:2020年6月25日 11:17  点击:3942

事件(event),这个词儿对于初学者来说,往往总是显得有些神秘,不易弄懂。而这些东西却往往又是编程中常用且非常重要的东西。大家都知道windows消息处理机制的重要,其实C#事件就是基于windows消息处理机制的,只是封装的更好,让开发者无须知道底层的消息处理机制,就可以开发出强大的基于事件的应用程序来。

先来看看事件编程有哪些好处。

在以往我们编写这类程序中,往往采用等待机制,为了等待某件事情的发生,需要不断地检测某些判断变量,而引入事件编程后,大大简化了这种过程:

- 使用事件,可以很方便地确定程序执行顺序。

- 当事件驱动程序等待事件时,它不占用很多资源。事件驱动程序与过程式程序最大的不同就在于,程序不再不停地检查输入设备,而是呆着不动,等待消息的到来,每个输入的消息会被排进队列,等待程序处理它。如果没有消息在等待,则程序会把控制交回给操作系统,以运行其他程序。

- 事件简化了编程。操作系统只是简单地将消息传送给对象,由对象的事件驱动程序确定事件的处理方法。操作系统不必知道程序的内部工作机制,只是需要知道如何与对象进行对话,也就是如何传递消息。

有了这么多好处,看来我们的确有必要掌握它。俗话说:“难了不会,会了不难”。就让我们一步一步开始吧...

要讲事件,必然要讲到委托(delegate)。它们之间的关系可以通过一个浅显的比方来说明,这个比方可能不是十分恰当。比如你要租一个房屋,这是一个事件,那么委托就是房屋租赁中介,当你把租房子的消息告知中介后,中介就会产生出一套符合你要求的房屋租赁方案来。再由中介执行这套方案,你便租得了这个房屋,即事件被处理了。当然你也可以不通过中介,直接找房东,但如果没有互联网等工具,你如何得到谁出租房屋的信息?话题扯远了。

委托(delegate)

委托可以理解成为函数指针,不同的是委托是面向对象,而且是类型安全的。关于委托的理解,可以参考我的另一篇文章《C#委托之个人理解》。

事件(event)

我们可以把事件编程简单地分成两个部分:事件发生的类(书面上叫事件发生器)和事件接收处理的类。事件发生的类就是说在这个类中触发了一个事件,但这个类并不知道哪个个对象或方法将会加收到并处理它触发的事件。所需要的是在发送方和接收方之间存在一个媒介。这个媒介在.NET Framework中就是委托(delegate)。在事件接收处理的类中,我们需要有一个处理事件的方法。好了,我们就按照这个顺序来实现一个捕获键盘按键的程序,来一步一步说明如何编写事件应用程序。

1、首先创建一个自己的EventArgs类。

引自MSDN:

EventArgs是包含事件数据的类的基类,此类不包含事件数据,在事件引发时不向事件处理程序传递状态信息的事件会使用此类。如果事件处理程序需要状态信息,则应用程序必须从此类派生一个类来保存数据。

因为在我们键盘按键事件中要包含按键信息,所以要派生一个KeyEventArgs类,来保存按键信息,好让后面知道按了哪个键。

internal class KeyEventArgs : EventArgs 
{
	private char keychar;
	public KeyEventArgs( char keychar ) : base() 
	{
		this.keychar = keychar;
		public char Keychar
		{
		get
		{
		return keychar;
	}
}
}

2、再创建一个事件发生的类KeyInputMonitor,这个类用于监控键盘按键的输入并触发一个事件:

internal class KeyInputMonitor 
{
  // 创建一个委托,返回类型为void,两个参数
  public delegate void KeyDownHandler( object sender, KeyEventArgs e );
  // 将创建的委托和特定事件关联,在这里特定的事件为KeyDown
  public void Run() 
  {
    bool finished = false;
    do 
    {
      Console.WriteLine( "Input a char" );
      string response = Console.ReadLine();
      char responsechar = ( response == "" ) ? ' ' : char.ToUpper( response[0] );
      switch( responsechar ) 
      {
        case 'X':
        finished = true;
        break;
        default:
        // 得到按键信息的参数
        KeyEventArgs keyEventArgs = new KeyEventArgs( responsechar );
        // 触发事件
        KeyDown( this, keyEventArgs );
        break;
      }
    }
    while( !finished );
  }
}

这里注意KeyDown( this, KeyEventArgs );一句,这就是触发事件的语句,并将事件交由KeyDownHandler这个委托来处理,委托指定事件处理方法去处理事件,这就是事件接收方的类的事情了。参数this是指触发事件的对象就是本身这个对象,keyEventArgs包含了按键信息。

3、最后创建一个事件接收方的类,这个类先产生一个委托实例,再把这个委托实例添加到产生事件对象的事件列表中去,这个过程又叫订阅事件。然后提供一个方法回显按键信息。

internal class EventReceiver 
{
  public EventReceiver( KeyInputMonitor monitor ) 
  {
    // 产生一个委托实例并添加到KeyInputMonitor产生的事件列表中
    monitor.KeyDown += new KeyInputMonitor.KeyDownHandler( this.OnKeyDown );
  }
  private void OnKeyDown(object sender, KeyEventArgs e) 
  {
    // 真正的事件处理函数
    Console.WriteLine( "Capture key: {0}", e.Keychar );
  }
}

4、看一下如何调用

public class MainEntryPoint
{
public static void Start() 
{
  // 实例化一个事件发送器
  KeyInputMonitor monitor = new KeyInputMonitor();
  // 实例化一个事件接收器
  EventReceiver eventReceiver = new EventReceiver( monitor );
  // 运行
  monitor.Run();
}
}

总结:

C#中使用事件需要的步骤:

1.创建一个委托

2.将创建的委托与特定事件关联(.Net类库中的很多事件都是已经定制好的,所以他们也就有相应的一个委托,在编写关联事件处理程序--也就是当有事件发生时我们要执行的方法的时候我们需要和这个委托有相同的签名)

3.编写事件处理程序

4.利用编写的事件处理程序生成一个委托实例

5.把这个委托实例添加到产生事件对象的事件列表中去,这个过程又叫订阅事件

C#中事件产生和实现的流程:

1.定义A为产生事件的实例,a为A产生的一个事件

2.定义B为接收事件的实例,b为处理事件的方法

3.A由于用户(程序编写者或程序使用者)或者系统产生一个a事件(例如点击一个Button,产生一个Click事件)

4.A通过事件列表中的委托对象将这个事件通知给B

5.B接到一个事件通知(实际是B.b利用委托来实现事件的接收)

6.调用B.b方法完成事件处理

public class A 
{
  public delegate void EventHandler(object sender);
  public void Run() 
  {
    Console.WriteLine("Trigger an event.");
    a(this);
  }
}
class B 
{
  public B(A a) 
  {
    a.a += new A.EventHandler(this.b);
  }
  private void b(object sender) 
  {
    Console.WriteLine("Received and handled an event." );
    Console.Read();
  }
}

[!--infotagslink--]

相关文章

  • C#实现简单的登录界面

    我们在使用C#做项目的时候,基本上都需要制作登录界面,那么今天我们就来一步步看看,如果简单的实现登录界面呢,本文给出2个例子,由简入难,希望大家能够喜欢。...2020-06-25
  • 浅谈C# 字段和属性

    这篇文章主要介绍了C# 字段和属性的的相关资料,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下...2020-11-03
  • C#中截取字符串的的基本方法详解

    这篇文章主要介绍了C#中截取字符串的的基本方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-03
  • C#实现简单的Http请求实例

    这篇文章主要介绍了C#实现简单的Http请求的方法,以实例形式较为详细的分析了C#实现Http请求的具体方法,需要的朋友可以参考下...2020-06-25
  • C#连接SQL数据库和查询数据功能的操作技巧

    本文给大家分享C#连接SQL数据库和查询数据功能的操作技巧,本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友参考下吧...2021-05-17
  • C#中new的几种用法详解

    本文主要介绍了C#中new的几种用法,具有很好的参考价值,下面跟着小编一起来看下吧...2020-06-25
  • 使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序)

    这篇文章主要介绍了使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • C#开发Windows窗体应用程序的简单操作步骤

    这篇文章主要介绍了C#开发Windows窗体应用程序的简单操作步骤,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-12
  • C#从数据库读取图片并保存的两种方法

    这篇文章主要介绍了C#从数据库读取图片并保存的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...2021-01-16
  • C#和JavaScript实现交互的方法

    最近做一个小项目不可避免的需要前端脚本与后台进行交互。由于是在asp.net中实现,故问题演化成asp.net中jiavascript与后台c#如何进行交互。...2020-06-25
  • C++调用C#的DLL程序实现方法

    本文通过例子,讲述了C++调用C#的DLL程序的方法,作出了以下总结,下面就让我们一起来学习吧。...2020-06-25
  • 轻松学习C#的基础入门

    轻松学习C#的基础入门,了解C#最基本的知识点,C#是一种简洁的,类型安全的一种完全面向对象的开发语言,是Microsoft专门基于.NET Framework平台开发的而量身定做的高级程序设计语言,需要的朋友可以参考下...2020-06-25
  • C#变量命名规则小结

    本文主要介绍了C#变量命名规则小结,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-09
  • C#绘制曲线图的方法

    这篇文章主要介绍了C#绘制曲线图的方法,以完整实例形式较为详细的分析了C#进行曲线绘制的具体步骤与相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • C# 中如何取绝对值函数

    本文主要介绍了C# 中取绝对值的函数。具有很好的参考价值。下面跟着小编一起来看下吧...2020-06-25
  • c#自带缓存使用方法 c#移除清理缓存

    这篇文章主要介绍了c#自带缓存使用方法,包括获取数据缓存、设置数据缓存、移除指定数据缓存等方法,需要的朋友可以参考下...2020-06-25
  • c#中(&&,||)与(&,|)的区别详解

    这篇文章主要介绍了c#中(&&,||)与(&,|)的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25
  • 经典实例讲解C#递归算法

    这篇文章主要用实例讲解C#递归算法的概念以及用法,文中代码非常详细,帮助大家更好的参考和学习,感兴趣的朋友可以了解下...2020-06-25
  • C#学习笔记- 随机函数Random()的用法详解

    下面小编就为大家带来一篇C#学习笔记- 随机函数Random()的用法详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • C#中list用法实例

    这篇文章主要介绍了C#中list用法,结合实例形式分析了C#中list排序、运算、转换等常见操作技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25