WPF 路由事件

news/2024/11/14 13:00:30/文章来源:https://www.cnblogs.com/ywtssydm/p/18380852
一、什么是路由事件?
根据MSDN定义:功能定义:路由事件是一种可以针对元素树中的多个侦听器(而不是仅针对引发该事件的对象)调用处理程序的事件。
实现定义:路由事件是由 类的实例支持的 CLR 事件, RoutedEvent 由事件 Windows Presentation Foundation (WPF) 系统处理。
典型的 WPF 应用程序中包含许多元素。 无论这些元素是在代码中创建还是在 XAML 中声明,它们存在于彼此关联的元素树关系中。二、路由策略
路由事件使用以下三种路由策略之一:Bubbling【冒泡】: 调用事件源上的事件处理程序。 路由事件随后会路由到后续的父级元素,直到到达元素树的根。 大多数路由事件都使用冒泡路由策略。 冒泡路由事件通常用于报告来自不同控件或其他 UI 元素的输入或状态变化。Direct【直接】: 只有源元素本身才有机会调用处理程序以进行响应。 这类似于窗体用于事件的Windows路由"。 但是,与标准 CLR 事件不同,直接路由事件支持类处理 (类处理在即将发布的) 节中进行了说明,并且 和 可以使用 EventSetter或 EventTrigger 。

Tunneling【隧道】: 最初将调用元素树的根处的事件处理程序。 随后,路由事件将朝着路由事件的源节点元素(即引发路由事件的元素)方向,沿路由线路传播到后续的子元素。 合成控件的过程中通常会使用或处理隧道路由事件,通过这种方式,可以有意地禁止复合部件中的事件,或者将其替换为特定于整个控件的事件。冒泡策略
事件的冒泡策略,就像水里的泡泡一样,从底往上,逐级触发。路由事件随后会路由到后续的父级元素,直到到达元素树的根。 大多数路由事件都使用冒泡路由策略。 冒泡路由事件通常用于报告来自不同控件或其他 UI 元素的输入或状态变化。

  <Window x:Class="WpfApp1.OneWindow"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:WpfApp1"mc:Ignorable="d"x:Name="w1"Title="OneWindow" Height="350" Width="500" Button.Click="btn1_Click"><Grid x:Name="gdOuter" Button.Click="btn1_Click"><StackPanel x:Name="sp1" Button.Click="btn1_Click"><Grid x:Name="gd1" Button.Click="btn1_Click"><Button x:Name="btn1" Content="点我" Click="btn1_Click" Margin="5" Padding="5" FontSize="18"></Button></Grid><RichTextBox x:Name="txtInfo" Margin="5" MinHeight="100"  ></RichTextBox></StackPanel></Grid>
</Window>
隧道策略
隧道策略事件,与冒泡策略刚好相反, 最初将调用元素树的根处的事件处理程序。 随后,路由事件将朝着路由事件的源节点元素(即引发路由事件的元素)方向,沿路由线路传播到后续的子元素。所有的隧道策略模式事件,都是以Preview开头。隧道事件有时又称作预览事件,这是由该对所使用的命名约定决定的。隧道策略由顶至下,逐层下探,直至最好一个元素,如下所示:

 <Window x:Class="WpfApp1.TwoWindow"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:WpfApp1"mc:Ignorable="d"Name="w1"Title="TwoWindow" Height="350" Width="500" Button.PreviewMouseDown="btn1_PreviewMouseDown"><Grid><Grid x:Name="gdOuter" Button.PreviewMouseDown="btn1_PreviewMouseDown"><StackPanel x:Name="sp1" Button.PreviewMouseDown="btn1_PreviewMouseDown"><Grid x:Name="gd1" Button.PreviewMouseDown="btn1_PreviewMouseDown"><Button x:Name="btn1" Content="点我" PreviewMouseDown="btn1_PreviewMouseDown" Margin="5" Padding="5" FontSize="18"></Button></Grid><RichTextBox x:Name="txtInfo" Margin="5" MinHeight="100"  ></RichTextBox></StackPanel></Grid></Grid>
</Window>
注意:在 WPF 中提供的输入事件通常是以隧道/浮升对实现的。事件阻止
在实际应用中,如果不想事件采用冒泡或隧道策略,向上或向下执行,则需要设置e.Handled=true即可,如下所示:

 private void btn1_Click(object sender, RoutedEventArgs e){this.txtInfo.AppendText(string.Format("当前响应事件对象:{0},响应事件原始对象:{1}\r\n", (sender as FrameworkElement).Name, e.OriginalSource));e.Handled = true;}
三、后台添加路由事件
路由事件既可以通过XAML的方式,进行设置,也可以通过后台代码的方式进行设置,如下所示:

      /// <summary>/// ThreeWindow.xaml 的交互逻辑/// </summary>public partial class ThreeWindow : Window{public ThreeWindow(){InitializeComponent();this.btn1.AddHandler(Button.ClickEvent, new RoutedEventHandler(btn1_Click));this.gd1.AddHandler(Button.ClickEvent, new RoutedEventHandler(btn1_Click));this.sp1.AddHandler(Button.ClickEvent, new RoutedEventHandler(btn1_Click));this.gdOuter.AddHandler(Button.ClickEvent, new RoutedEventHandler(btn1_Click));this.w1.AddHandler(Button.ClickEvent, new RoutedEventHandler(btn1_Click));}private void btn1_Click(object sender, RoutedEventArgs e){this.txtInfo.AppendText(string.Format("当前响应事件对象:{0},响应事件原始对象:{1}\r\n", (sender as FrameworkElement).Name, e.OriginalSource));//e.Handled = true;
         }}
四、自定义路由事件
创建自定义路由事件,步骤如下:
1、声明并注册路由事件。
2、为路由事件添加CLR事件包装器。
3、创建可以激发事件的方法。
具体操作步骤如下:首先创建的自定义控件,继承自Button按钮,如下所示:
 namespace WpfApp1{/// <summary>/// 自定义路由事件/// </summary>public class TimeButton:Button{/// <summary>/// 声明和注册路由事件/// </summary>public static readonly RoutedEvent TimeEvent = EventManager.RegisterRoutedEvent("Time", RoutingStrategy.Bubble, typeof(EventHandler<TimeEventArgs>), typeof(TimeButton));/// <summary>/// 事件包装器/// </summary>public event RoutedEventHandler Time{add { this.AddHandler(TimeEvent, value); }remove{this.RemoveHandler(TimeEvent, value);}}/// <summary>/// 重写方法,激发事件/// </summary>protected override void OnClick(){base.OnClick();TimeEventArgs e = new TimeEventArgs(TimeEvent,this);e.ClickTime = DateTime.Now;this.RaiseEvent(e);}}public class TimeEventArgs : RoutedEventArgs {public TimeEventArgs(RoutedEvent routedEvent, object source) : base(routedEvent, source) { }public DateTime ClickTime { get; set; }}}
在窗体中,创建自定义按钮实例。如下所示:
 <Window x:Class="WpfApp1.A1Window"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:WpfApp1"mc:Ignorable="d"Title="A1Window" Height="450" Width="800"><Grid x:Name="gd1" local:TimeButton.Time="timeButton1_Time"><StackPanel x:Name="sp1" local:TimeButton.Time="timeButton1_Time"><local:TimeButton x:Name="timeButton1" Content="报时" Time="timeButton1_Time"></local:TimeButton><RichTextBox x:Name="txtInfo" Margin="5" MinHeight="100"  ></RichTextBox></StackPanel></Grid></Window>
然后实现事件函数,如下所示:
private void timeButton1_Time(object sender, TimeEventArgs e){this.txtInfo.AppendText(string.Format("当前响应事件对象:{0},响应事件时间为:{1}\r\n", (sender as FrameworkElement).Name, e.ClickTime.ToString("yyyy-MM-dd hh:mm:ss.fff")));}

来源:https://blog.csdn.net/weixin_48083386/article/details/139350212

 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【转载】Win11优化大小核调度(无需重启)

出处:https://bbs.saraba1st.com/2b/thread-2140520-1-1.html 打开隐藏电源管理选项: 管理员模式运行cmd,分别输入: powercfg -attributes SUB_PROCESSOR 7f2f5cfa-f10c-4823-b5e1-e93ae85f46b5 -ATTRIB_HIDE powercfg -attributes SUB_PROCESSOR 93b8b6dc-0698-4d1c-9ee4-…

【Pytorch教程】迅速入门Pytorch深度学习框架

@目录前言1.tensor基础操作1.1 tensor的dtype类型1.2 创建tensor(建议写出参数名字)1.2.1 空tensor(无用数据填充)API示例1.2.2 全一tensor1.2.3 全零tensor1.2.4 随机值[0,1)的tensor1.2.5 随机值为整数且规定上下限的tensorAPI示例1.2.6 随机值均值0方差1的tensor1.2.7 从…

AMD显卡VGA转HDMI花屏或者雪花屏解决办法

本以为是显卡或者显示屏或者转接线有问题,查阅资料后得出VGA转HDMI花屏或者雪花屏解决办法: 进入AMD控制面板。点击设置 - > 显示器 - > 覆盖 - > 禁用HDCP 即可完美解决问题。

AIGC时代,如何为“数据飞轮”提速

本文从技术角度,具体拆解DataLeap-找数助手、开发助手的实现方式,详AIGC如何为企业数智化转型赋能。更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群 企业通过数智化转型实现降本增效,已经成为行业共识。而随着AIGC时代到来,企业的…

windows 安装nginx

1.进入下载页面下载window版本 安装 2.解压, 直接运行 exe就行 3.使用nssm 将exe文件 作为服务运行 4.配置conf/nginx.conf 的配置文件

使用yum命令报错

报错如下Could not retrieve mirrorlist http://mirrorlist.centos.org/?release=7&arch=x86_64&repo=os&infra=stock error was 14: curl#6 - "Could not resolve host: mirrorlist.centos.org; Unknown error"One of the configured repositories fai…

EXITS:基于极值点低标注成本弱监督实例分割 | CVPR 2024

EXITS将极值点视为真实实例掩模的一部分并将它们传播以识别潜在前景和背景点,所有这些都用于训练伪标签生成器,然后由生成器给出的伪标签反过来用于最终模型的监督学习。 来源:晓飞的算法工程笔记 公众号论文: Extreme Point Supervised Instance Segmentation论文地址:htt…

Swahili-text:华中大推出非洲语言场景文本检测和识别数据集 | ICDAR 2024

论文提出了一个专门针对斯瓦希里语自然场景文本检测和识别的数据集,这在当前研究中是一个未充分开发的语言领域。数据集包括976张带标注的场景图像,可用于文本检测,以及8284张裁剪后的图像用于识别。 来源:晓飞的算法工程笔记 公众号论文: The First Swahili Language Scen…

Codeforces Round 968 (Div. 2)

良心出题人给了中文题解!!! A. Turtle and Good Strings 长度为 \(n\) 的字符串至少分成两段,使 \(\forall i < j\) ,第 \(i\) 段的首字符不等于第 \(j\) 段的尾字符 第一个字符一定作为首字符,最后一个字符一定作为尾字符,只要判断这两个字符是否相等即可 相等的话一…

【日记】这个月花了好多钱(1317 字)

正文这几天都好热。热到人不想动,只想睡觉。今天写文章发现自己有个很显著的特点,就是在有个框架之后,具体细节完全没有预设。我只能像马尔可夫链一样,形成一个比较窄的窗口,接着这个窗口里的情节往下写,否则我就会宕机,写不出来。整个故事情节看起来也就比较散。马尔可…

个人博客导航如何创建更有个性化?

个人博客导航如何创建更有个性化?创建个性化博客导航是一个既实用又能体现个人风格的过程。以下是一些步骤和建议,帮助你完成这一过程:一、确定导航需求和内容明确目的:首先,你需要明确博客导航的主要目的是什么,比如是为了方便读者查找特定内容、展示你的博客结构,还是…

线程基础

生命周期创建线程 class MyThread extends Thread{@Overridepublic void run(){ System.out.println("Hello World"); } }class MyRunnable implements Runnable{@Overridepublic void run() { System.out.println("Hello World"); } }public class Test1 …