C#事件驱动编程:标准事件模式完全指南
事件驱动是GUI编程的核心逻辑。当程序被按钮点击、按键或定时器中断时,如何规范处理事件?.NET框架通过EventHandler委托给出了标准答案。
🔍 一、EventHandler委托:事件处理的基石
public delegate void EventHandler(object sender, EventArgs e);
参数解析:
- object sender → 事件源对象(任意类型)
- EventArgs e → 事件数据容器(默认为空)
核心特性: - 强制统一签名:所有事件处理器必须匹配此参数结构
- 返回值必须为void
- EventArgs是空壳基类,实际数据需通过派生类扩展
💡 设计意义:通过标准化参数,实现事件处理接口的统一化,避免签名混乱。
⚙️ 二、基础事件实现(无数据传递)
// 发布者
class Incrementer {
public event EventHandler CountedADozen; // 声明标准事件
public void DoCount() {
for(int i=1; i<100; i++)
if(i%12 == 0 && CountedADozen != null)
CountedADozen(this, null); // 触发事件(无数据)
}
}
// 订阅者
class Dozens {
void IncrementDozensCount(object source, EventArgs e) {
DozensCount++; // 忽略参数e
}
}
适用场景:仅需事件通知,无需传递额外数据(如界面按钮点击)
🚀 三、扩展事件数据:自定义EventArgs
步骤详解:
1️⃣ 创建派生类存储数据
public class IncrementerEventArgs : EventArgs {
public int IterationCount { get; set; } // 自定义数据属性
}
2️⃣ 使用泛型委托声明事件
class Incrementer {
// 泛型委托绑定自定义参数类型
public event EventHandler<IncrementerEventArgs> CountedADozen;
}
3️⃣ 触发事件时传递数据
public void DoCount() {
var args = new IncrementerEventArgs(); // 创建数据对象
for(int i=1; i<100; i++) {
if(i%12 == 0 && CountedADozen != null) {
args.IterationCount = i; // 设置数据
CountedADozen(this, args); // 传递数据对象
}
}
}
4️⃣ 订阅者接收数据
void IncrementDozensCount(object source, IncrementerEventArgs e) {
Console.WriteLine($"触发位置:{e.IterationCount}"); // 使用自定义数据
}
⚠️ 命名规范:自定义类名需以EventArgs结尾
🔄 四、事件处理程序管理
动态增删处理器:
// 添加处理器
p.SimpleEvent += s.MethodA;
p.SimpleEvent += s.MethodB;
// 移除指定处理器
p.SimpleEvent -= s.MethodB;
关键规则:
- 同个处理器多次注册时,-=只移除最后一次注册
- 事件触发前必须检查null(避免空引用异常)
- 线程安全场景需使用Invoke同步调用
场景 | 方案 | 示例 |
---|---|---|
无数据传递 | 原生EventHandler | 按钮点击事件 |
需传递数据 | EventHandler+自定义EventArgs | 进度条数值更新 |
多订阅者管理 | +=/-=动态注册 | 动态加载模块 |
// 终极模板
public event EventHandler<CustomEventArgs> MyEvent;
public class CustomEventArgs : EventArgs { ... }
🚀 行动建议:
- 立即重构旧事件代码,采用标准模式
- 复杂数据场景务必使用自定义EventArgs
- 关键事件添加try-catch异常处理
原文地址:https://blog.csdn.net/weixin_42291376/article/details/149109249
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!