《深入浅出WPF》读书笔记.8路由事件

devtools/2024/11/15 6:04:37/

《深入浅出WPF》读书笔记.8路由事件

背景

路由事件是直接响应事件的变种。直接响应事件,事件触发者和事件响应者必须显示订阅。而路由事件的触发者和事件响应者之间的没有显示订阅,事件触发后,事件响应者安装事件监听器,当事件传递到此时,事件处理器进行响应,并决定事件是否继续传递。

路由事件

WPF的两种树形结构

逻辑树

逻辑树就是UI树

可视元素树

单独组件的构成元素树

事件基础

路由事件

<Window x:Class="RouteEventDemo.RouteEventDemo1"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:RouteEventDemo"mc:Ignorable="d"Title="RouteEventDemo1" Height="450" Width="600"><Grid x:Name="gridRoot" Background="LightSalmon" ButtonBase.Click="gridRoot_Click"><Grid x:Name="gridA"><Grid.ColumnDefinitions><ColumnDefinition Width="100*"></ColumnDefinition><ColumnDefinition Width="100*"></ColumnDefinition></Grid.ColumnDefinitions><Canvas Grid.Column="0"><Button x:Name="btn1" Width="100" Height="40" Content="leftButton" Canvas.Left="100" Canvas.Top="197"></Button></Canvas><Canvas Grid.Column="1"><Button x:Name="btn2" Width="100" Height="40" Content="rightButton" Canvas.Left="100" Canvas.Top="197"/></Canvas></Grid></Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;namespace RouteEventDemo
{/// <summary>/// RouteEventDemo1.xaml 的交互逻辑/// </summary>public partial class RouteEventDemo1 : Window{public RouteEventDemo1(){InitializeComponent();//this.gridRoot.AddHandler(Button.ClickEvent, new RoutedEventHandler(btn_Clicked));}private void btn_Clicked(object sender, RoutedEventArgs e){MessageBox.Show(string.Format("OriginalSource:{0},Source:{1}",(e.OriginalSource as FrameworkElement).Name,(e.Source as FrameworkElement).Name));}private void gridRoot_Click(object sender, RoutedEventArgs e){MessageBox.Show(string.Format("OriginalSource:{0},Source:{1}", (e.OriginalSource as FrameworkElement).Name, (e.Source as FrameworkElement).Name));}}
}

事件传递路线

自定义路由事件

自定义路由分三步

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;namespace RouteEventDemo
{public class TimeButton : Button{//声明注册路由事件public static readonly RoutedEvent ReportTimeEvent = EventManager.RegisterRoutedEvent("ReportTime", RoutingStrategy.Tunnel, typeof(EventHandler<ReportTimeEventArgs>), typeof(TimeButton));//CLR事件包装器public event RoutedEventHandler ReportTime{add { this.AddHandler(ReportTimeEvent, value); }remove { this.RemoveHandler(ReportTimeEvent, value); }}//激发路由事件protected override void OnClick(){//保证原有功能base.OnClick();ReportTimeEventArgs args = new ReportTimeEventArgs(ReportTimeEvent, this);args.ClickTime = DateTime.Now;this.RaiseEvent(args);}}
}
<Window x:Class="RouteEventDemo.UserDefinedRouteEventDemo"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:RouteEventDemo"mc:Ignorable="d"local:TimeButton.ReportTime="ReportTimeHandler"Title="UserDefinedRouteEventDemo" Height="450" Width="600"><Grid x:Name="grd1" local:TimeButton.ReportTime="ReportTimeHandler"><Grid x:Name="grd2" local:TimeButton.ReportTime="ReportTimeHandler"><Grid x:Name="grd3" local:TimeButton.ReportTime="ReportTimeHandler"><StackPanel x:Name="sp1" local:TimeButton.ReportTime="ReportTimeHandler"><ListBox x:Name="lb1" local:TimeButton.ReportTime="ReportTimeHandler"></ListBox><local:TimeButton local:TimeButton.ReportTime="ReportTimeHandler" Width="100" Height="40" Content="ReportTime"></local:TimeButton></StackPanel></Grid></Grid></Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;namespace RouteEventDemo
{/// <summary>/// UserDefinedRouteEventDemo.xaml 的交互逻辑/// </summary>public partial class UserDefinedRouteEventDemo : Window{public UserDefinedRouteEventDemo(){InitializeComponent();}private void ReportTimeHandler(object sender, ReportTimeEventArgs e){FrameworkElement frameworkElement = sender as FrameworkElement;if (frameworkElement != null){string timeStr = e.ClickTime.ToString();string content = string.Format("{0}到达{1}", timeStr, frameworkElement.Name);this.lb1.Items.Add(content);}//指定到某个元素停止if (frameworkElement.Name == "grd2"){e.Handled = true;}}}
}

OriginalSource和Source

Source:元素树

OriginalSource:可视化元素树

<UserControl x:Class="RouteEventDemo.UserControl1"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:RouteEventDemo"mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="120"><Border BorderBrush="Orange" CornerRadius="3" BorderThickness="5"><Button x:Name="innerBtn" Content="OK"></Button></Border>
</UserControl>
<Window x:Class="RouteEventDemo.SourceDemo"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:RouteEventDemo"mc:Ignorable="d"Title="SourceDemo" Height="450" Width="800"><Grid x:Name="gd1"><local:UserControl1 x:Name="myUc" Margin="5"></local:UserControl1></Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;namespace RouteEventDemo
{/// <summary>/// SourceDemo.xaml 的交互逻辑/// </summary>public partial class SourceDemo : Window{public SourceDemo(){InitializeComponent();this.AddHandler(Button.ClickEvent, new RoutedEventHandler(btn_Clicked));}private void btn_Clicked(object sender, RoutedEventArgs e){MessageBox.Show(string.Format("OriginalSource:{0},Source:{1}", (e.OriginalSource as FrameworkElement).Name, (e.Source as FrameworkElement).Name));}}
}

附加事件

附加事件和路由事件的区别在于宿主是否为UI控件。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;namespace RouteEventDemo
{public class Student{public static readonly RoutedEvent NameChangedEvent = EventManager.RegisterRoutedEvent("NameChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Student));public static void AddNameChangedHandler(DependencyObject o, RoutedEventHandler h){UIElement element = o as UIElement;if (element != null){element.AddHandler(NameChangedEvent, h);}}public static void RemoveNameChangedHandler(DependencyObject o,RoutedEventHandler h){UIElement element = o as UIElement;if (element != null){element.RemoveHandler(NameChangedEvent, h);}}public string Name { get; set; }public int Id { get; set; }}
}
<Window x:Class="RouteEventDemo.AttachedEventDemo"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:RouteEventDemo"mc:Ignorable="d"Title="AttachedEventDemo" Height="450" Width="600"><Grid x:Name="grdMain"><Button x:Name="btn1" Content="点击一下" Width="120" Height="40" Click="btn1_Click"></Button></Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;namespace RouteEventDemo
{/// <summary>/// AttachedEventDemo.xaml 的交互逻辑/// </summary>public partial class AttachedEventDemo : Window{public AttachedEventDemo(){InitializeComponent();//this.grdMain.AddHandler(Student.NameChangedEvent, new RoutedEventHandler(StudentNameChangedEventHandler));Student.AddNameChangedHandler(this.grdMain, new RoutedEventHandler(StudentNameChangedEventHandler));}private void StudentNameChangedEventHandler(object sender, RoutedEventArgs e){MessageBox.Show((e.OriginalSource as Student).Id.ToString());}private void btn1_Click(object sender, RoutedEventArgs e){Student student = new Student() { Id = 1, Name = "Tom" };student.Name = "Tim";RoutedEventArgs args = new RoutedEventArgs(Student.NameChangedEvent,student);this.btn1.RaiseEvent(args);}}
}

git地址

GitHub - wanghuayu-hub2021/WpfBookDemo: 深入浅出WPF的demo

得加快学习速度了,记得点赞关注哦~👉⭐


http://www.ppmy.cn/devtools/102244.html

相关文章

Java重修笔记 第四十三天 Set 集合、HashSet 类

Set 接口 1. 它是无序的&#xff08;添加和取出的顺序不一致&#xff0c;但取出的结果是固定的&#xff09;&#xff0c;没有索引 2. Set 接口也是 Collection 的子接口&#xff0c;所以继承了 Collection 的方法 3. Set 接口的遍历方式有两种&#xff0c;迭代器和增强 for…

pyautogui的一些自动化示例,附代码

以下为您提供一些 pyautogui 的自动化示例及代码&#xff1a; 模拟鼠标点击和移动&#xff1a;import pyautogui # 获取屏幕的宽度和高度 screen_width, screen_height pyautogui.size() # 将鼠标移动到屏幕中心 pyautogui.moveTo(screen_width / 2, screen_height / 2) # 在…

如何从人机环境系统中捕捉语义

从人机环境系统中捕捉语义主要涉及将系统中的数据和信息转化为具有实际意义的内容&#xff0c;以便更好地理解和响应用户的需求。以下是几种常见的方法来捕捉语义&#xff1a; 1. 自然语言处理 (NLP) 方法&#xff1a;使用自然语言处理技术来分析和理解用户输入的文本或语音。N…

甄选范文“NoSQL数据库技术及其应用”,软考高级论文,系统架构设计师论文

论文真题 随着互联网web2.0网站的兴起,传统关系数据库在应对web2.0 网站,特别是超大规模和高并发的web2.0纯动态SNS网站上已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。 NoSQL(Not only SQL )的产生就是为了解…

数据库系统 第27节 NoSQL 数据库

NoSQL数据库是一类不遵循传统关系型数据库管理系统&#xff08;RDBMS&#xff09;的数据库。它们设计用于处理大量的非结构化或半结构化数据&#xff0c;并且通常具有更好的水平扩展能力。下面是对您提到的几种NoSQL数据库类型的详细讲解&#xff1a; 文档数据库&#xff1a; 文…

SSH弱口令爆破服务器

一、实验背景 1、概述 使用kali的hydra进行ssh弱口令爆破&#xff0c;获得服务器的用户名和口令&#xff0c;通过 ssh远程登录服务器。 2、实验环境 kali攻击机&#xff1a;192.168.1.107 centos服务器&#xff1a;192.168.1.105 二、前置知识 1、centos设置用户并设置弱…

利用住宅代理进行版权保护,有效监控和打击侵权行为

引言 为什么需要版权保护&#xff1f; 版权保护常见的挑战有哪些&#xff1f; 如何进行版权保护&#xff1f; 住宅代理在版权保护中的实际应用场景 总结 引言 在数字时代&#xff0c;信息和内容的传播速度和范围达到了前所未有的高度。无论是图像、视频、音乐还是文字内容…

STM32外部中断事件控制器-EXTI

EXTI简介&#xff1a; EXTI 是 External Interrupt 的缩写&#xff0c;表示外部中断事件控制器。EXTI 可以监测指定 GPIO 口的电平信号变化&#xff0c;并在检测到指定条件时&#xff0c;向内核的中断控制器 NVIC 发出中断申请。NVIC 在裁决后&#xff0c;如果满足条件&#xf…