WPF新手村教程(三)路由事件如何为?
摘要:WPF个人文档(三)—— 路由事件 一.路由事件 先来说一下分类,参考某位博主以及博主参考的对应资料分类,先留个印象,然后我们逐步讲解 路由事件:冒泡事件、隧道事件(预览事件)、直接事件(直达事件) 事件(从作用角度划分):生命周期事件、输
WPF个人文档(三)—— 路由事件
一.路由事件
先来说一下分类,参考某位博主以及博主参考的对应资料分类,先留个印象,然后我们逐步讲解
路由事件:冒泡事件、隧道事件(预览事件)、直接事件(直达事件)
事件(从作用角度划分):生命周期事件、输入事件(鼠标事件、键盘输入事件、触控事件)
1.路由 —— 在既定结构中,按照规则传播信号的路径
路径 → 静态结构
规则 → 传播策略
信号 → 事件
路由:网络工程术语,指分组从源到目的地时,决定端到端路径的网络范围的进程
路由的本质:信息从哪里来,要往哪里去,经过哪些节点
1.最原始的路由:网络
在互联网里,一个数据包从电脑中发出去,不是直线飞到服务器
它要经过多个路由器,每个路由器根据规则决定“下一跳”
不是简单传递,而是“根据结构和规则决定传播路径”
2.抽象到程序中
当一个事件发生时,它不一定只通知一个对象,它可能沿着某种结构传播
而这整条“传播路径”就是我们所说的路由
# 比如 UI 是一棵树
Window
└── Grid
└── Button
当 Button 被点击时,事件可以:
只在 Button 内处理(直达)
往上通知 Grid → Window(冒泡)
或者从 Window 先往下检查(隧道)
2.路由事件
前面我们已经提到过路由事件的分类,现在我们对其进行较为详细的 吐槽 讲解
路由事件:冒泡事件、隧道事件(预览事件)、直接事件(直达事件)
1.🌱冒泡事件 → 由里往外
传播方向:子 → 父
典型例子:MouseDown、KeyDown、Click
使用场景:子控件触发行为,但由父容器统一处理
统一日志
权限判断
容器级行为控制
MVVM 中命令转发
代码示例:
// 只要窗口里任何 Button 被点击,Window 都能收到
this.AddHandler(Button.ClickEvent, new RoutedEventHandler(Window_Click));
优点:解耦
缺点:调试时要小心,可能在半路被 e.Handled = true 截断
2.🌱隧道事件 → 从外往里
传播方向:父 → 子
事件先从 Window 往下走到最底层控件,然后才进入冒泡阶段
即:父级可以“预先审查”事件
典型事件格式:PreviewXXX
比如:PreviewMouseDown、PreviewKeyDown
经典场景:全局快捷键、输入过滤、行为拦截
代码示例:
// 行为拦截:子控件接收不到按键 F5
private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.F5)
e.Handled = true;
// e.Handled = true 表示这个按键的路由到此结束
// 这个事件已经被处理完了,不需要继续传播
// 1.阻止事件继续沿当前路由传播
// 2.阻止对应的后续阶段执行
}
3.🌱直达事件 → 不传播
传播方向:只在当前控件触发,不向上也不向下
典型例子:MouseEnter、MouseLeave、Loaded
[!IMPORTANT]
为什么它只在当前控件触发,不向上不向下?
因为语义上不适合传播
鼠标进入 Button,不等于进入它父 Grid
如果冒泡,会产生逻辑污染
直达事件适合:
局部状态改变
单控件行为
不需要结构参与的逻辑
总结
🌱冒泡事件:我干了件事,要向上级汇报。
