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

news/2024/9/18 7:24:06/ 标签: visual studio, c#, microsoft, 学习, 笔记, wpf

《深入浅出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/news/1517126.html

相关文章

SpringBoot -在Axis2中,RPCServiceClient调用WebService

在 Axis2 中,RPCServiceClient 是一种用于调用 WebService 的客户端实现。下面是如何将它们 结合起来使用的一个示例: 步骤 1: 添加依赖 首先,在 pom.xml 文件中添加 Axis2 的相关依赖。 <dependencies><!-- 其他依赖 --><dependency><groupId>…

拓扑排序-

基本原理 就是存在一个入度为0的点和一个出度为0的点 然后图中所有点都是指向同一个方向&#xff1b; /* 拓扑序列&#xff1a; 特点&#xff1a;有向无环图 判断&#xff1a;判断所有的点是否入度为0 换句话 就是入度为0的点个数是否满点的总数 过程&#xff1a;建图、入度数…

2024HarmonyOS应用开发者高级认证最新整理题库和答案(已收录182道 )

更新截止2024-08-27,完整题库一共182道题,足够覆盖90%考题,如有新题和遗漏我会持续补充 所有题目的选项都是打乱顺序的,记答案不要记序号 完整题库请在我的网盘下载或查看在线文档 完整题库在线文档预览 单选(已收录102道) 1 . 以下哪个装饰器用来表示并发共享对象。(B) A. @…

通过Python绘制不同数据类型适合的可视化图表

在数据可视化中&#xff0c;对于描述数值变量与数值变量之间的关系常见的有散点图和热力图&#xff0c;以及描述数值变量与分类变量之间的关系常见的有条形图&#xff0c;饼图和折线图&#xff0c;可以通过使用Python的matplotlib和seaborn库来绘制图表进行可视化表达&#xff…

超详细!!!uniapp通过unipush全流程实现app消息推送

云风网 云风笔记 云风知识库 一、HBuilder新建APP项目 二、配置推送服务 1、登录Dcloud开发者中心开发者中心&#xff0c;查看我的应用 2、生成云端证书 3、创建平台信息 4、配置推送服务信息 这里需要关联服务空间&#xff0c;可以申请免费服务空间进行测试 三、代码配置 1…

Java笔试面试题AI答之线程(24)

文章目录 139. 简述为什么 wait(), notify()和 notifyAll()必须在同步方法或 者同步块中被调用&#xff1f;140. 简述为什么 Thread 类的 sleep()和 yield ()方法是静态的 &#xff1f;1. sleep() 方法2. yield() 方法总结 141. 简述同步方法和同步块&#xff0c;哪个是更好的选…

hydra密码爆破工具详细使用教程

Hydra是一个强大的密码爆破工具&#xff0c;可以用来测试网络系统的弱口令。下面是使用Hydra的基本教程&#xff1a; 1. 安装Hydra 可以从Hydra的官方网站&#xff08;https://github.com/vanhauser-thc/thc-hydra&#xff09;下载最新版本的Hydra&#xff0c;并按照安装说明进…

spring boot 配置监听多端口

如何实现Spring Boot配置监听多端口 1. 概述 在Spring Boot应用中&#xff0c;有时候需要监听多个端口&#xff0c;比如同时监听HTTP和HTTPS端口。本文将介绍如何实现在Spring Boot应用中配置监听多端口。 2. 流程表格 步骤 操作 1 添加依赖 2 创建多端口配置类 3 …

turtlebot 测试 Gazebo Harmonic ROS Jazzy

源码移植后理论上支持所有Gazebo和ROS版本&#xff0c;但花费时间较多。 只推荐学习Gazebo 经典版和Gazebo Harmonic以及之后版本。 在中间的过渡版本&#xff0c;不推荐学习。 Gazebo经典版包括Gazebo 7 Gazebo 9 Gazebo 11。 Gazebo Harmonic 和 ROS2 jazzy 安装和测试-CSDN博…

vue3+ts el-table 鼠标移动到某单元格内时就显示 tooltip

在Vue 3和Element Plus中&#xff0c;要在鼠标移动到表格某个单元格上时显示tooltip&#xff0c;可以使用el-tooltip组件&#xff0c;并结合表格的cell-mouse-enter和cell-mouse-leave事件。 <template> <el-table :data"tableData" cell-mouse-e…

深度学习-批量与动量【Datawhale X 李宏毅苹果书 AI夏令营】

实际工程中使用批量和动量可以对抗鞍点或局部最小值。 批量&#xff1a; 在计算梯度的时候不会用所有数据计算损失。类比我们考试复习时&#xff0c;一个单元一个单元的知识点输入&#xff0c;所有单元都输入就是一整个轮回。而这一个单元用深度学习的术语来说就是批量&#x…

CSRF 概念及防护机制

概述 CSRF&#xff08;Cross-Site Request Forgery&#xff09;&#xff0c;即跨站请求伪造&#xff0c;是一种网络攻击方式。在这种攻击中&#xff0c;恶意用户诱导受害者在不知情的情况下执行某些操作&#xff0c;通常是利用受害者已经登录的身份&#xff0c;向受害者信任的…

【精选】基于数据可视化的智慧社区内网平台

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

华为AC旁挂二层组网配置详解:从DHCP部署到无线业务配置,完成网络搭建

组网需求 AC组网方式&#xff1a;旁挂二层组网。 DHCP部署方式&#xff1a; AC作为DHCP服务器为AP分配IP地址。 防火墙作为DHCP服务器为STA分配IP地址。 业务数据转发方式&#xff1a;直接转发。 网络拓扑图 对于旁边路直接转发&#xff0c;优点就是数据流量不经过AC&…

决策树和随机森林介绍

hello大家好&#xff0c;俺是没事爱瞎捣鼓又分享欲爆棚的叶同学&#xff01;&#xff01;&#xff01;今天我来给大家介绍一下决策树与随机森林&#xff0c;说起随机森林俺还有件很久远的丑事&#xff0c;之前有关课的结课作业就是用模型训练并预测&#xff0c;那时我比较天真&…

OpenCV(第二关--读取图片和摄像头)实例+代码

以下内容&#xff0c;皆为原创&#xff0c;制作不易&#xff0c;感谢大家的关注和点赞。 一.读取图片 我们来读取图片&#xff0c;当你用代码读取后&#xff0c;可能会发现。怎么跟上传的图片颜色有些许的不一样。因为OpenCV的颜色通道是BGR&#xff0c;而我们平常用的matplotl…

百日筑基第六十天-学习一下Tomcat

百日筑基第六十天-学习一下Tomcat 一、Tomcat 顶层架构 Tomcat 中最顶层的容器是 Server&#xff0c;代表着整个服务器&#xff0c;从上图中可以看出&#xff0c;一个 Server可以包含至少一个 Service&#xff0c;用于具体提供服务。Service 主要包含两个部分&#xff1a;Conn…

Flask SQLALchemy 的使用

Flask SQLALchemy 的使用 安装 Flask-SQLAlchemy配置 Flask-SQLAlchemy定义模型创建数据库和表插入和查询数据更新和删除数据迁移数据库总结Flask-SQLAlchemy 是一个 Flask 扩展,它简化了 Flask 应用中 SQLAlchemy 的使用。SQLAlchemy 是一个强大的 SQL 工具包和对象关系映射(…

【AI智能体】在AI浪潮中,程序员如何在这复杂的环境中生存下去

在这个瞬息万变的时代&#xff0c;人工智能&#xff08;AI&#xff09;如同一阵狂风&#xff0c;席卷了各行各业&#xff0c;尤其是程序员这一群体。面对AI的迅猛发展&#xff0c;程序员们不仅要适应新的技术潮流&#xff0c;更要在这场变革中找到自己的立足之地。如何在AI浪潮…

Shader笔记:光照与阴影1

引&#xff1a;旋转动画&#xff08;三角函数&#xff09; float3 rotationY(float3 vertex){float c cos(_Time.y*_Speed);float s sin(_Time.y*_Speed);float3x3 m {c,0,s,0,1,0,-s,0,c};return mul(m,vertex); } v2f vert (a2v v) {v2f o;o.pos UnityObjectToClipPos(r…