当前位置: 首页 > news >正文

WPF路由事件

一、路由事件的核心概念

路由事件(Routed Event)是 WPF 引入的事件系统,与传统 CLR 事件的主要区别在于:它可以在元素树中 "传播",允许多个元素对同一个事件进行处理。
 

元素树:WPF 的 UI 控件通过嵌套形成树形结构(如Grid包含StackPanelStackPanel包含Button),称为元素树。

事件源:触发事件的原始元素(如用户点击的Button)。

传播路径:事件从源元素出发,沿元素树向上或向下传播的路径。

二、路由事件的三种传播策略

路由事件有三种传播方式,决定了事件在元素树中的传播路径:
 
传播类型说明典型应用
冒泡(Bubble) 从事件源向上传播至元素树的根节点(由内向外) 普通交互事件(如ClickMouseDown
隧道(Tunnel) 从元素树的根节点向下传播至事件源(由外向内) 预览事件(如PreviewMouseDownPreviewKeyDown),通常用于提前拦截事件
直接(Direct) 仅在事件源上触发,不传播 类似传统 CLR 事件,如MouseEnter

简单理解 冒泡:最里面的控件传播至外面 例如Grid包含StackPanelStackPanel包含Button,Button点击-->StackPanel-->Grid

                隧道:点击Button后 Grid-->StackPanel-->Button

三、实战:使用WPF内置路由事件

<Window x:Class="RoutedEventDemo.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="路由事件演示" Height="300" Width="400"Button.Click="Window_Click"> <!-- 窗口处理Button的Click事件 --><Grid Button.Click="Grid_Click"> <!-- Grid处理Button的Click事件 --><StackPanel Margin="50" Button.Click="StackPanel_Click"> <!-- StackPanel处理Button的Click事件 --><Button Content="点击我" Width="100" Height="30" Click="Button_Click"/> <!-- Button自身处理Click事件 --></StackPanel></Grid>
</Window>
using System.Windows;namespace RoutedEventDemo
{public partial class MainWindow : Window{public MainWindow(){InitializeComponent();}// Button自身的Click事件处理private void Button_Click(object sender, RoutedEventArgs e){MessageBox.Show("Button处理了Click事件");// 若设置e.Handled = true,事件将停止传播(Grid和Window不会收到)// e.Handled = true;
        }// StackPanel处理Button的Click事件(冒泡到这里)private void StackPanel_Click(object sender, RoutedEventArgs e){MessageBox.Show("StackPanel处理了Click事件");}// Grid处理Button的Click事件(继续冒泡)private void Grid_Click(object sender, RoutedEventArgs e){MessageBox.Show("Grid处理了Click事件");}// Window处理Button的Click事件(最终冒泡到根元素)private void Window_Click(object sender, RoutedEventArgs e){MessageBox.Show("Window处理了Click事件");}}
}

从上面例子可以看出每个树级别的元素都有一个Button.Click,他都可以相应这个事件,可以在后台代码不同或者相同的方法中处理。

四、自定义路由事件

1.自定义控件,有点像依赖属性

using System.Windows;
using System.Windows.Controls;
namespace 自定义路由事件
{// 自定义控件,作为路由事件的所有者public class CustomButton : Button{// 声明并注册路由事件public static readonly RoutedEvent CustomClickEvent =EventManager.RegisterRoutedEvent("CustomClick",// 事件名称RoutingStrategy.Bubble,// 传播策略(冒泡)typeof(RoutedEventHandler),// 事件处理程序类型typeof(CustomButton));// 所有者类型// 2. 创建CLR事件包装器(供XAML绑定)public event RoutedEventHandler CustomClick{add { AddHandler(CustomClickEvent, value); }remove { RemoveHandler(CustomClickEvent, value); }}// 重写基础按钮的点击事件protected override void OnClick(){base.OnClick(); // 确保基础按钮的功能正常// 3. 创建已注册和包装的本身的路由事件实例,并引发它RoutedEventArgs args = new RoutedEventArgs(CustomClickEvent, this);RaiseEvent(args);// 引发自定义事件
        }}
}

2.界面代码

<Window x:Class="自定义路由事件.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:自定义路由事件"mc:Ignorable="d"Title="自定义路由事件示例" Height="300" Width="400"><StackPanel local:CustomButton.CustomClick="StackPanel_CustomClick" Margin="10"><Border BorderBrush="Black" BorderThickness="2" Padding="10" local:CustomButton.CustomClick="Border_CustomClick"><local:CustomButton Content="点击我" CustomClick="CustomButton_CustomClick"Width="100" Height="30"/></Border><TextBlock x:Name="statusText" Margin="0,20,0,0"/></StackPanel>
</Window>

从上面代码可以看出 StackPanel ,Border, local:CustomButton 都绑定了自定义的路由事件

3.界面后台代码

using System.Windows;
namespace 自定义路由事件
{public partial class MainWindow : Window{public MainWindow(){InitializeComponent();}// 按钮自身的事件处理private void CustomButton_CustomClick(object sender, RoutedEventArgs e){statusText.Text = "按钮自身处理了CustomClick事件";}// 边框的事件处理private void Border_CustomClick(object sender, RoutedEventArgs e){statusText.Text += "\n边框也处理了CustomClick事件";// 如果想阻止事件继续冒泡,可以取消事件// e.Handled = true;
        }// StackPanel的事件处理private void StackPanel_CustomClick(object sender, RoutedEventArgs e){statusText.Text += "\nStackPanel也处理了CustomClick事件";}}
}

从上到下控件一级一级的冒泡

http://www.hskmm.com/?act=detail&tid=16040

相关文章:

  • VS2022 不支持 .NET Framework 4.0 的解决方法
  • 【Origin】数据分析后的图,提取到外部图表
  • P3747 [六省联考 2017] 相逢是问候
  • B1I、B1C、B2a双频北斗卫星定位芯片AT9850B-F7N-22
  • Wi-Fi技能——网络安全
  • idea打开properties文件中文乱码问题
  • 2025/9/22
  • 人机共生:AI如何重塑招聘全流程,赋能HR战略升级
  • hot100题简单题
  • Scanner 和if
  • python自动化操作PDF
  • 注意事项
  • 完整教程:【数据结构】 ArrayList深入解析
  • 产品经理如何借力项目管理软件,驾驭复杂项目并准时上线?
  • 公钥密码与可证安全概述
  • Python标准库enum模块实现枚举类
  • Filter过滤器
  • 程序员的旅行神器:用AI提示词工程解决选择困难症
  • 修改人大金仓V8数据库时间
  • BUUCTF-babyheap_0ctf_2017题解(含详细过程与思路分析)
  • 油猴(Tampermonkey)插件从安装到使用
  • 【EF Core】框架底层的数据库连接管理
  • iNeuOS工业互联网操作系统,更新计量数据处理方式和在线报表,实现能源管理基础功能
  • React 展示Markdown内容 - 教程
  • 西电PCB设计指南第4章学习笔记
  • 图像处理去除噪点验证码的识别逻辑实践
  • Java文件上传和其他参数一起提交的案例
  • 三维模型非结构化网格生成
  • Windows 环境变量配置
  • Playwright MCP浏览器自动化指南 - 详解