C#中的路由事件(Routed Events)

路由事件的基本概念

路由事件是WPF中特有的事件系统,它允许事件在可视化树中"路由"传递,具有以下特点:

  1. 事件路由方向

    • 冒泡(Tunneling):从事件源向根元素传递

    • 隧道(Bubbling):从根元素向事件源传递

    • 直接(Direct):仅在事件源处理

  2. 事件处理机制

    • 允许多个元素处理同一事件

    • 可以在父元素中处理子元素的事件

路由事件的实现原理

核心组件

  1. EventManager类:负责注册和管理路由事件

  2. RoutedEvent类:表示路由事件本身

  3. RoutedEventArgs类:包含路由事件数据

事件路由过程

  1. 事件在源元素触发

  2. 根据路由策略向上或向下传递

  3. 每个元素都有机会处理事件

  4. 可以通过e.Handled = true终止路由

代码示例

示例1:自定义路由事件

public class MyButton : Button
{// 1. 注册路由事件public static readonly RoutedEvent MyCustomEvent = EventManager.RegisterRoutedEvent("MyCustom",                     // 事件名称RoutingStrategy.Bubble,         // 路由策略typeof(RoutedEventHandler),     // 事件处理程序类型typeof(MyButton));             // 拥有者类型// 2. 提供CLR事件包装器public event RoutedEventHandler MyCustom{add { AddHandler(MyCustomEvent, value); }remove { RemoveHandler(MyCustomEvent, value); }}// 3. 触发事件的方法protected virtual void OnMyCustom(){RoutedEventArgs args = new RoutedEventArgs(MyCustomEvent);RaiseEvent(args);}protected override void OnClick(){base.OnClick();OnMyCustom(); // 点击时触发我们的自定义事件}
}

示例2:使用冒泡路由事件

<Window x:Class="WpfApp.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="路由事件示例" Height="350" Width="525"ButtonBase.Click="Window_Click"> <!-- 在Window级别处理所有按钮点击 --><StackPanel><Button Content="按钮1" Margin="5" Padding="5"/><Button Content="按钮2" Margin="5" Padding="5"/><Button Content="按钮3" Margin="5" Padding="5" Click="Button3_Click"/></StackPanel>
</Window>// 代码后台
private void Window_Click(object sender, RoutedEventArgs e)
{Button btn = e.OriginalSource as Button;if (btn != null){MessageBox.Show($"Window处理了按钮 {btn.Content} 的点击事件");// e.Handled = true; // 如果取消注释,Button3_Click将不会执行}
}private void Button3_Click(object sender, RoutedEventArgs e)
{MessageBox.Show("Button3的专属点击处理");e.Handled = true; // 阻止事件继续冒泡
}

示例3:隧道路由事件应用

<Window x:Class="WpfApp.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"PreviewMouseDown="Window_PreviewMouseDown"><Grid MouseDown="Grid_MouseDown" PreviewMouseDown="Grid_PreviewMouseDown"><Button Content="点击我" Width="100" Height="30"MouseDown="Button_MouseDown" PreviewMouseDown="Button_PreviewMouseDown"/></Grid>
</Window>// 代码后台
private void Window_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{Debug.WriteLine("Window PreviewMouseDown (隧道)");
}private void Grid_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{Debug.WriteLine("Grid PreviewMouseDown (隧道)");
}private void Button_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{Debug.WriteLine("Button PreviewMouseDown (隧道)");
}private void Button_MouseDown(object sender, MouseButtonEventArgs e)
{Debug.WriteLine("Button MouseDown (冒泡)");
}private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{Debug.WriteLine("Grid MouseDown (冒泡)");
}

输出顺序:

  1. Window PreviewMouseDown (隧道)

  2. Grid PreviewMouseDown (隧道)

  3. Button PreviewMouseDown (隧道)

  4. Button MouseDown (冒泡)

  5. Grid MouseDown (冒泡)

实际应用场景

  1. 全局事件处理:在父容器中统一处理子元素事件

  2. 组合控件:自定义控件内部元素事件冒泡到控件级别

  3. 事件拦截:在路由过程中拦截并处理事件

  4. 输入事件处理:处理鼠标/键盘等输入事件的隧道和冒泡阶段

路由事件与CLR事件的区别

特性路由事件CLR事件
传播方式可视化树中路由直接绑定
处理者多个元素可处理单一处理者
事件参数RoutedEventArgsEventArgs
注册方式EventManager.RegisterRoutedEventevent关键字
典型应用WPF控件交互普通类事件处理

路由事件是WPF强大交互能力的基础,合理利用可以极大简化复杂UI的事件处理逻辑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/401.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

抽象工厂模式深度解析:从原理到与应用实战

作者简介 我是摘星&#xff0c;一名全栈开发者&#xff0c;专注 Java后端开发、AI工程化 与 云计算架构 领域&#xff0c;擅长Python技术栈。热衷于探索前沿技术&#xff0c;包括大模型应用、云原生解决方案及自动化工具开发。日常深耕技术实践&#xff0c;乐于分享实战经验与…

力扣面试150题--克隆图

Day 61 题目描述 思路 /* // Definition for a Node. class Node {public int val;public List<Node> neighbors;public Node() {val 0;neighbors new ArrayList<Node>();}public Node(int _val) {val _val;neighbors new ArrayList<Node>();}public N…

Axure零基础跟我学:展开与收回

亲爱的小伙伴,如有帮助请订阅专栏!跟着老师每课一练,系统学习Axure交互设计课程! Axure产品经理精品视频课https://edu.csdn.net/course/detail/40420 课程主题:Axure菜单展开与收回 课程视频:

第十三节:第四部分:集合框架:HashMap、LinkedHashMap、TreeMap

Map集合体系 HashMap集合的底层原理 HashMap集合底层是基于哈希表实现的 LinkedHashMap集合的底层原理 TreeMap集合的底层原理 代码&#xff1a; Student类 package com.itheima.day26_Map_impl;import java.util.Objects;public class Student implements Comparable<Stu…

命名管道实现本地通信

目录 命名管道实现通信 命名管道通信头文件 创建命名管道mkfifo 删除命名管道unlink 构造函数 以读方式打开命名管道 以写方式打开命名管道 读操作 写操作 析构函数 服务端 客户端 运行结果 命名管道实现通信 命名管道通信头文件 #pragma#include <iostream> #include &l…

Spring 框架之IOC容器加载重要组件

1.读取配置 如果配置了这样的Bean: 或者 或者 这些是不同定义bean的方式&#xff0c; 他们最终都会生成bean。 那Spring为了生成bean代码复用&#xff0c;使用统一的创建流程&#xff0c;所以通过多态方式读取不同的配置会有不同的读取器&#xff0c;读取完后后续创建bean的流程…

数字证书_CA_详解

目录 一、数字证书简介 二、 CA&#xff08;证书颁发机构&#xff09; (一) 证书链&#xff08;信任链&#xff09; 1. 根证书 2. 中间证书 3. 网站证书 (二) 抓包软件的证书链与信任机制 1. 抓包通信流程 2. 证书链伪造与信任验证流程 (三) 关于移动设备的CA 一、数…

Qt Creator 11.0创建ROS2 Humble工程

Qt Creator 11.0创建ROS2 Humble项目工程 安装ROSProjectManager插件创建ROS2项目在src下添加packagegit clone ROS2功能包编译运行安装ROSProjectManager插件 安装ROSProjectManager的主要流程参考官方的流程,地址(ros_qtc_plugin)。 此处采用二进制安装: sudo apt inst…

卡西欧模拟器:Windows端功能强大的计算器

引言 大家还记得初中高中时期用的计算器吗&#xff1f;今天给大家分享的就是一款windows端的卡西欧计算器。 软件介绍 大家好&#xff0c;我是逍遥小欢。 CASIO fx-9860G是一款功能强大的图形计算器&#xff0c;适用于数学、科学和工程计算。以下是其主要功能和特点的详细介…

软件工程专业的本科生应该具备哪些技能

软件工程专业的本科生需要具备扎实的技术基础、良好的开发流程认知和一定的软技能&#xff0c;以适应软件开发行业的需求。以下从技术技能、开发流程与工具、软技能、实践能力等维度整理核心技能清单&#xff0c;供参考&#xff1a; 一、核心技术技能 1. 编程语言 - 必学基础语…

微信小程序实现运动能耗计算

微信小程序实现运动能耗计算 近我做了一个挺有意思的微信小程序&#xff0c;能够实现运动能耗的计算。只需要输入性别、年龄、体重、运动时长和运动类型这些信息&#xff0c;就能算出对应的消耗热量。 具体来说&#xff0c;在小程序里&#xff0c;性别不同&#xff0c;身体基…

点评中是如何实现短信登录的

点评中是如何实现短信登录的 首先在这个项目中 我们主要还是通过session来实现的验证码登录 根据这个图片我们很清楚的知道 首先要制造一个随机的验证码以确保并且保存到redis中&#xff08;等下我会说为什么不存在session中&#xff09;接下来前端传来验证码 后端校验后 判断…