12.2 事件的应用 - 图1

事件拥有者通过内部逻辑触发事件

用户按下按钮执行操作,看似是用户的外部操作引起按钮的 Click 事件触发,实际不然,详细情况大致如下:

  1. 当用户点击图形界面的按钮时,实际是用户的鼠标向计算机硬件发送了一个电信号。Windows 检测到该电信号后,就查看一下鼠标当前在屏幕上的位置。当 Windows 发现鼠标位置处有个按钮,且包含该按钮的窗口处于激活状态,它就通知该按钮,用户按下了,然后按钮的内部逻辑开始执行
  2. 典型的逻辑是按钮快速地把自己绘制一遍,绘制成自己被按下的样子,然后记录当前的状态为被按下了。紧接着如果用户松开了鼠标,Windows 就把消息传递给按钮,按钮内部逻辑又开始执行,把自己绘制成弹起的状态,记录当前的状态为未被按下
  3. 按钮内部逻辑检测到,按钮被执行了连续的按下、松开动作,即按钮被点击了。按钮马上使用自己的 Click 事件通知外界,自己被点击了。如果有别的对象订阅了该按钮的 Click 事件,这些事件的订阅者就开始工作

简言之:用户操作通过 Windows 调用了按钮的内部逻辑,最终还是按钮的内部逻辑触发了 Click 事件。

事件示例

Timer 的一些成员,其中闪电符号标识的两个就是事件:
图片.png
通过查看 Timer 的成员,我们不难发现一个对象最重要的三类成员:

  • 属性(小扳手):对象或类当前处于什么状态
  • 方法(小方块):它能做什么
  • 事件(小闪电):它能在什么情况下通知谁 ```csharp using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Timers; //需要引用新的名称空间

namespace tttlll { class Program { static void Main(string[] args) { // 1.事件拥有者 timer Timer timer = new Timer(); timer.Interval = 1000; //Interval:时间间隔的长短,1000ms,即1s

  1. // 3.事件的响应者 boy
  2. Boy boy = new Boy();
  3. Girl girl = new Girl();
  4. // 2.事件 Elapsed,5.事件订阅 +=(+=后面跟上事件响应者的事件处理器)
  5. timer.Elapsed += boy.Action;
  6. timer.Elapsed += girl.Action;
  7. timer.Start();
  8. Console.ReadLine();
  9. }
  10. }
  11. class Boy
  12. {
  13. //4.事件处理器 自动生成的Action方法
  14. internal void Action(object sender, ElapsedEventArgs e)
  15. {
  16. Console.WriteLine("Jump!");
  17. }
  18. }
  19. class Girl
  20. {
  21. internal void Action(object sender, ElapsedEventArgs e)
  22. {
  23. Console.WriteLine("Sing!");
  24. }
  25. }

}

  1. <a name="w4Rvf"></a>
  2. ##
  3. <a name="7Xnr4"></a>
  4. ## 几种事件订阅方式
  5. <a name="b10f9ede"></a>
  6. ### ⭐事件拥有者和事件响应者是完全不同的两个对象
  7. ![](https://cdn.nlark.com/yuque/0/2018/png/101969/1539307270956-ddd7ed12-287a-4e76-90bb-dd4429c5a970.png#from=url&id=oMWsn&margin=%5Bobject%20Object%5D&originHeight=223&originWidth=579&originalType=binary&ratio=1&status=done&style=none)<br />这种组合方式是 MVC、MVP 等设计模式的雏形。
  8. Click 事件与上例的 Elapsed 事件的第二个参数的数据类型不同,即这两个事件的约定是不同的。
  9. **也就是说,你不能拿影响 Elapsed 事件的事件处理器去响应 Click 事件 —— 因为遵循的约束不同,所以他们是不通用的。**
  10. ```csharp
  11. using System;
  12. using System.Collections.Generic;
  13. using System.Linq;
  14. using System.Text;
  15. using System.Threading.Tasks;
  16. using System.Windows.Forms;
  17. namespace tttlll
  18. {
  19. class Program
  20. {
  21. static void Main(string[] args)
  22. {
  23. //1.事件拥有者 form
  24. Form form = new Form();
  25. //3.事件响应者 controller
  26. Controller controller = new Controller(form);
  27. form.ShowDialog();
  28. }
  29. }
  30. class Controller
  31. {
  32. private Form form;
  33. public Controller(Form form)
  34. {
  35. if (form!=null)
  36. {
  37. this.form = form;
  38. //2.事件 Click 5.事件订阅 +=
  39. this.form.Click += this.FormClicked;
  40. }
  41. }
  42. //4.事件处理器 FormClicked
  43. private void FormClicked(object sender, EventArgs e)
  44. {
  45. this.form.Text = DateTime.Now.ToString();
  46. }
  47. }
  48. }

⭐⭐事件的拥有者和响应者是同一个对象

该示例中事件的拥有者和响应者都是 from。示例中顺便演示了继承:
12.2 事件的应用 - 图3

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Windows.Forms;
  7. namespace tttlll
  8. {
  9. class Program
  10. {
  11. static void Main(string[] args)
  12. {
  13. //1.事件拥有者 3.事件响应者 都是 form
  14. MyForm form = new MyForm();
  15. //2.事件 Click 5.事件订阅 +=
  16. form.Click += form.FormClicked;
  17. form.ShowDialog();
  18. }
  19. }
  20. class MyForm : Form
  21. {
  22. //4.事件处理器 FormClicked
  23. internal void FormClicked(object sender, EventArgs e)
  24. {
  25. this.Text = DateTime.Now.ToString();
  26. }
  27. }
  28. }

⭐⭐⭐事件的拥有者是事件响应者的一个字段成员

12.2 事件的应用 - 图4

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Windows.Forms;
  7. namespace tttlll
  8. {
  9. class Program
  10. {
  11. static void Main(string[] args)
  12. {
  13. MyForm form = new MyForm();
  14. form.ShowDialog();
  15. }
  16. }
  17. //3.事件响应者 MyForm对象
  18. class MyForm : Form
  19. {
  20. private TextBox textBox;
  21. //1.事件拥有者 button(button是Form的字段成员)
  22. private Button button;
  23. public MyForm()
  24. {
  25. this.textBox = new TextBox();
  26. this.button = new Button();
  27. this.Controls.Add(this.button);
  28. this.Controls.Add(this.textBox);
  29. //2.事件 Click 5.事件订阅 +=
  30. this.button.Click += this.ButtonClicked;
  31. this.button.Text = "Say Hello";
  32. this.button.Top = 20;
  33. }
  34. //4.事件处理器 ButtonClicked
  35. private void ButtonClicked(object sender, EventArgs e)
  36. {
  37. this.textBox.Text = "Hello,World!";
  38. }
  39. }
  40. }