有没有想过在. NET 中已经有了事件机制, 为什么在 WPF 中不直接使用. NET 事件要加入路由事件来取代事件呢? 最直观的原因就是典型的 WPF 应用程序使用很多元素关联和组合起来, 是否还记得在 WPF 自学入门(一)XAM 基本知识中提到过两棵树, 逻辑树 LogicalTree 和可视化树 VisualTree, 那么它们分别是什么?
举个例子:
上面的代码就是逻辑树 LogicalTree, 一个 Grid 里面镶嵌了其他控件或布局组件, 相当于一棵树中的叶子而可视化树 VisualTree 是什么? 它就是一个树中的树叶里面的结构, 用放大镜看一下, 其实叶子里面的结构也是一颗树结构
举个例子:
既然 WPF 中使用这样的一个设计理念, 路由事件就是特别为 WPF 而生, 它的功能就是可以把一个事件从触发点沿着树向上或者向下传播, 需要对这个事件作出反应的地方就添加一个监听器, 就会有相应的反应, 当然, 它的传递是可以用代码来停止 好了, 我已经大概了解了一些路由事件下面先来了解一下 WPF 内置的路由事件和原理, 然后我们来创建一个属于自己的路由事件
1WPF 内置的路由事件
新建 WPF 项目, 在页面上放置按钮然后在 Window,Grid,Button 标签上使用 MouseDown 事件, 如下图
添加后置代码
调试运行, 鼠标右键点击按钮, 会依次弹出下列三个对话框
ButtonMouseDown 事件被触发:
GridMouseDown 事件被触发:
WindowMouseDown 事件被触发:
我点击的是按钮, 为什么 Grid 和 Window 也会引发事件呢? 其实这就是路由事件的机制, 引发的事件由源元素逐级传到上层的元素, Button>Grid>Window, 这样就导致这几个元素都接收到了事件(注意一定是鼠标右键, 否则引发不了事件)
如果想 Grid 和 Window 不处理这个事件, 只需要在 Button_MouseDown 这个方法中加上 e.Handled = true; 这样就表示事件已经被处理, 其他元素不需要再处理这个事件了
- private void Button_MouseDown(object sender, MouseButtonEventArgs e)
- {
- MessageBox.Show("Button 被点击!");
- e.Handled = true;
- }
如果想要 Grid 参与事件处理只需要给它 AddHandler 即可
grid.AddHandler(Grid.MouseDownEvent, new RoutedEventHandler(Grid_MouseDown), true);
到这里我想大家应该对路由事件有了大概认识了路由事件实际上分两类: 气泡事件和预览事件 (也叫做隧道事件) 上文中的例子就是气泡事件
2 内置路由事件学习总结:
气泡事件是 WPF 路由事件中最为常见, 它表示事件从源元素扩散传播到可视树, 直到它被处理或到达根元素这样我们就可以针对源元素的上方层级对象处理事件(例如 MouseDown)
预览事件采用另一种方式, 从根元素开始, 向下遍历元素树, 直到被处理或到达事件的源元素这样上游元素就可以在事件到达源元素之前先行截取并进行处理根据命名惯例, 预览事件带有前缀 Preview(例如 PreviewMouseDown)
气泡事件和预览事件区别
气泡事件: 在 Button 上点击, 首先弹出 Button, 再弹出 Grid, 最后弹出 Window
预览事件: 在 Button 上点击, 首先弹出 Window, 再弹出 Grid, 最后弹出 Button
看到了这个顺序区别, 那么我们加入 e.Handled=true 的时机也要不同
PS: 本人也是 WPF 的初学者, 如有不对的地方, 欢迎在评论区多多指教, 学习, 为了分享, 为了提高
来源: http://www.bubuko.com/infodetail-2521886.html