C#事件

  事件我认为是C#其中一个难点,绕来绕去的,如果刚开始学习的话会有些困难。最近因为有相应的需求,并且看了网上诸多大佬的文章后,自己也有了一定的应用经验和了解,于是写出来分享一下。

  我先打算用CLR via C#举得例子,就是电子邮件。我们工作或者日常生活中经常会用到电子邮件,当有某人往我们的邮箱发信息之后,会有相应的提示,我们看到了之后就肯定会打开邮箱去看邮件的内容是什么,这个就是事件的大体内容。事件可以用来处理很多问题,比如用户操作,如按键、点击、鼠标移动等等,或者是一些提示信息,如系统生成的通知。

  事件有三个要素:事件拥有者、事件订阅者、事件处理方法

  事件拥有者:也叫事件发布者,个人觉得用拥有者更方便理解,很显然,谁定义事件谁就是事件的拥有者。具体到代码中也就是哪个类中定义了的事件,那么这个类的实例就是事件的拥有者。
  事件订阅者:一直在监听事件是否触发。
  事件处理方法:事件触发后要执行的方法。当事件订阅者“发现”事件拥有者的事件被触发时,事件订阅者需要去执行的方法。一般来说,事件处理方法是定义在事件订阅者中。

  除了上面三个,还有一个要素就是事件,里面包含着这个事件的内容,比如邮件信息、按键信息什么的

  按照上面电子邮件的例子,电子邮箱这个系统即事件拥有者,用户即我们是事件订阅者,打开邮件进行查看这个操作就是事件处理方法。

 

  之后用我自己的例子,我感觉这个更直观,就是按键交互。在很多应用中用户是需要用键盘与系统进行交互,所以按键事件很常见。

  比如,当我们按下W键,在某个窗口就可以执行某个功能,这就可以用事件来解决。

  实例程序:

//键盘事件
    class KeyEvent : EventArgs
    {
        public string keycode { set; get; }
        public KeyEvent(string keycode)
        {
            this.keycode = keycode;
        }
    }
    
    //事件监听者
    class KeyListener
    {
        private KeyInputManager km;
        public KeyListener(KeyInputManager km)
        {
            km.keyEventHandler += HandleEvent;
        }
        //事件处理函数
        public void HandleEvent(Object sender, KeyEvent e)
        {
            Console.WriteLine("receive input " + e.keycode + " down");
            switch (e.keycode)
            {
                case "W":
                    Console.WriteLine("do W function");
                    break;
            }
        }
    }

    //事件拥有者
    class KeyInputManager
    {
        public event EventHandler<KeyEvent> keyEventHandler;

        public void GetInput(string keycode)
        {
            keyEventHandler(this, new KeyEvent(keycode));
        }
    }

    class Test
    {
        public static void Main()
        {
            KeyInputManager km = new KeyInputManager();
            KeyListener ke = new KeyListener(km);

            //模拟按键
            Thread.Sleep(2000);
            km.GetInput("K");
            Thread.Sleep(2000);
            km.GetInput("W");
            Thread.Sleep(2000);
            km.GetInput("E");

            return;
        }
    }

  KeyInputManager可以理解为键盘事件管理器,到时候全部按键的接受都可以给他,然后其他需要用到按键的窗口/模块可以通过事件的方式订阅键盘事件。这样就可以只通过一个管理器就可以有效管理很多窗口/模块。

  细节的话,就是想要使用自定义事件,首先就需要定义一个EventArgs

//键盘事件
    class KeyEvent : EventArgs
    {
        public string keycode { set; get; }
        public KeyEvent(string keycode)
        {
            this.keycode = keycode;
        }
    }

  需要定义一个类,继承自EventArgs

  然后事件拥有者需要的就是一个EventHandler<T>,T为之前自定义的事件类名,注意前面有个event

public event EventHandler<KeyEvent> keyEventHandler;

  到时候所有的事件订阅者订阅的其实就是这个

  还有事件处理函数,放在订阅者中,当订阅者监听到事件就会执行这个,注意参数,必须是这样,第一个参数是Object,e是EventHandler<T>中T同款

//事件处理函数
        public void HandleEvent(Object sender, KeyEvent e)
        {
            Console.WriteLine("receive input " + e.keycode + " down");
            switch (e.keycode)
            {
                case "W":
                    Console.WriteLine("do W function");
                    break;
            }
        }

  可以拥有多个事件处理函数,只需要在订阅的时候分好就行

km.keyEventHandler += HandleEvent;

  这个就是订阅,代表keyEventHandler事件触发,我就去执行HandleEvent这个函数。如果想取消监听,就是-=(如同字符串拼接)

  最后就是事件拥有者如何通知订阅者,如下

keyEventHandler(this, new KeyEvent(keycode));

  this代表通知者是自己本身这个事件拥有者,第二个参数则是之前定义的Event

 

  最终结果

   

 

  

posted @ 2021-11-29 12:01  可乐社区  阅读(176)  评论(0)    收藏  举报