事件拥有者通过内部逻辑触发事件
用户按下按钮执行操作,看似是用户的外部操作引起按钮的 Click 事件触发,实际不然,详细情况大致如下:
- 当用户点击图形界面的按钮时,实际是用户的鼠标向计算机硬件发送了一个电信号。Windows 检测到该电信号后,就查看一下鼠标当前在屏幕上的位置。当 Windows 发现鼠标位置处有个按钮,且包含该按钮的窗口处于激活状态,它就通知该按钮,用户按下了,然后按钮的内部逻辑开始执行
- 典型的逻辑是按钮快速地把自己绘制一遍,绘制成自己被按下的样子,然后记录当前的状态为被按下了。紧接着如果用户松开了鼠标,Windows 就把消息传递给按钮,按钮内部逻辑又开始执行,把自己绘制成弹起的状态,记录当前的状态为未被按下
- 按钮内部逻辑检测到,按钮被执行了连续的按下、松开动作,即按钮被点击了。按钮马上使用自己的 Click 事件通知外界,自己被点击了。如果有别的对象订阅了该按钮的 Click 事件,这些事件的订阅者就开始工作
简言之:用户操作通过 Windows 调用了按钮的内部逻辑,最终还是按钮的内部逻辑触发了 Click 事件。
事件示例
Timer 的一些成员,其中闪电符号标识的两个就是事件:
通过查看 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
// 3.事件的响应者 boy
Boy boy = new Boy();
Girl girl = new Girl();
// 2.事件 Elapsed,5.事件订阅 +=(+=后面跟上事件响应者的事件处理器)
timer.Elapsed += boy.Action;
timer.Elapsed += girl.Action;
timer.Start();
Console.ReadLine();
}
}
class Boy
{
//4.事件处理器 自动生成的Action方法
internal void Action(object sender, ElapsedEventArgs e)
{
Console.WriteLine("Jump!");
}
}
class Girl
{
internal void Action(object sender, ElapsedEventArgs e)
{
Console.WriteLine("Sing!");
}
}
}
<a name="w4Rvf"></a>
##
<a name="7Xnr4"></a>
## 几种事件订阅方式
<a name="b10f9ede"></a>
### ⭐事件拥有者和事件响应者是完全不同的两个对象
![](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 等设计模式的雏形。
Click 事件与上例的 Elapsed 事件的第二个参数的数据类型不同,即这两个事件的约定是不同的。
**也就是说,你不能拿影响 Elapsed 事件的事件处理器去响应 Click 事件 —— 因为遵循的约束不同,所以他们是不通用的。**
```csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace tttlll
{
class Program
{
static void Main(string[] args)
{
//1.事件拥有者 form
Form form = new Form();
//3.事件响应者 controller
Controller controller = new Controller(form);
form.ShowDialog();
}
}
class Controller
{
private Form form;
public Controller(Form form)
{
if (form!=null)
{
this.form = form;
//2.事件 Click 5.事件订阅 +=
this.form.Click += this.FormClicked;
}
}
//4.事件处理器 FormClicked
private void FormClicked(object sender, EventArgs e)
{
this.form.Text = DateTime.Now.ToString();
}
}
}
⭐⭐事件的拥有者和响应者是同一个对象
该示例中事件的拥有者和响应者都是 from。示例中顺便演示了继承:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace tttlll
{
class Program
{
static void Main(string[] args)
{
//1.事件拥有者 3.事件响应者 都是 form
MyForm form = new MyForm();
//2.事件 Click 5.事件订阅 +=
form.Click += form.FormClicked;
form.ShowDialog();
}
}
class MyForm : Form
{
//4.事件处理器 FormClicked
internal void FormClicked(object sender, EventArgs e)
{
this.Text = DateTime.Now.ToString();
}
}
}
⭐⭐⭐事件的拥有者是事件响应者的一个字段成员
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace tttlll
{
class Program
{
static void Main(string[] args)
{
MyForm form = new MyForm();
form.ShowDialog();
}
}
//3.事件响应者 MyForm对象
class MyForm : Form
{
private TextBox textBox;
//1.事件拥有者 button(button是Form的字段成员)
private Button button;
public MyForm()
{
this.textBox = new TextBox();
this.button = new Button();
this.Controls.Add(this.button);
this.Controls.Add(this.textBox);
//2.事件 Click 5.事件订阅 +=
this.button.Click += this.ButtonClicked;
this.button.Text = "Say Hello";
this.button.Top = 20;
}
//4.事件处理器 ButtonClicked
private void ButtonClicked(object sender, EventArgs e)
{
this.textBox.Text = "Hello,World!";
}
}
}