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

news2024/12/22 14:21:34

《深入浅出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.coloradmin.cn/o/2080317.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL EXPLAIN 完全解读

MySQL EXPLAIN 完全解读 一、一个EXPLAIN简单执行二、简单了解2.1. id&#xff1a;查询的标识符。2.2. select_type&#xff1a;查询的类型。2.3. table&#xff1a;输出结果集的表。2.4. type&#xff1a;连接类型&#xff0c;这是MySQL决定如何查找表中行的方法。2.5. possib…

学习之数据库相关概念

数据库相关概念 主流的关系型数据库管理系统&#xff1a;

HIVE 数据仓库工具之第一部分(讲解部署)

HIVE 数据仓库工具 一、Hive 概述1.1 Hive 是什么1.2 Hive 产生的背景1.3 Hive 优缺点1.3.1 Hive的优点1.3.2 Hive 的缺点 1.4 Hive在Hadoop生态系统中的位置1.5 Hive 和 Hadoop的关心 二、Hive 原理及架构2.1 Hive 的设计原理2.2 Hive 特点2.3 Hive的体现结构2.4 Hive的运行机…

数据集的使用

一、 Transform与dataset数据集的使用 import torchvisionfrom torch.utils.tensorboard import SummaryWriterdataset_transform torchvision.transforms.Compose([torchvision.transforms.ToTensor()])train_set torchvision.datasets.CIFAR10(root "./dataset"…

《中文Python穿云箭量化平台二次开发技术03》利用Tkinter高级模块设计自己策略代码编辑器及策略运行窗口

《中文Python穿云箭量化平台》是纯Python开发的量化平台&#xff0c;因此其中很多Python模块&#xff0c;我们可以自己设计新的量化工具&#xff0c;例如自己新的行情软件、新的量化平台、以及各种量化研究工具。 穿云箭自带指标公式源码运行模块&#xff0c;可以为其他量化平台…

基于云原生的一体化监控系统Day1

7.1 监控体系部署管理 7.2k8s集群层面监控 准备&#xff1a;部署k8s集群 master&#xff1a;192.168.192.128 node01&#xff1a;192.168.192.129 node02&#xff1a;192.168.192.130 1.prometheus架构&#xff1a; prometheus工作原理&#xff1a; 1.数据采集&#xff…

AI视频平台精选:国内外对比与推荐

原文&#xff1a;AI视频平台精选&#xff1a;国内外对比与推荐 国内外有多个平台可以生成AI视频&#xff0c;这些平台各有其独特的优点和缺点。以下是对一些主要平台的详细介绍&#xff0c;包括它们的优缺点&#xff0c;以及针对个人和自媒体用户的推荐。 国内平台 1. 快手可…

为Windows Terminal 配置zsh + Oh-My-Zsh

参考&#xff1a; 为Windows Terminal 配置zsh Oh-My-Zsh 【核心】https://juejin.cn/post/7229507721795993661 https://blog.cloudorz.com/post/configure-zsh-for-windows-terminal/ https://zhuanlan.zhihu.com/p/455925403 本文以 Git Bash 终端为基础&#xff0c;来…

android openGL ES详解——剔除

一、正面剔除 在绘制3D场景的时候,我们需要决定哪些部分是对观察者 可见的,或者哪些部分是对观察者不可⻅的.对于不可见的部分,应该及早丢弃.例如在⼀个不透明的墙壁后,就不应该渲染.这种情况叫做”隐藏⾯消除”(Hidden surface elimination). 立方体中的正背面 任何物体都有…

Vue 项目中使用路由鉴权实现网页进度条

概述 在 Web 开发中&#xff0c;用户界面的流畅性和交互性对用户体验至关重要。为了在页面跳转时给用户提供反馈&#xff0c;我们可以利用 NProgress 这样的第三方库来实现一个进度条。本文档将指导您如何在 Vue 项目中结合路由鉴权来实现这一功能。 准备工作 确保您已经安装…

YOLO后处理trick - 减少nms的计算次数、比较次数和空间消耗

目录 前言 1.问题分析 问题1&#xff1a;排序问题 问题2&#xff1a;极大值抑制问题 2.优化比较和计算次数 优化1&#xff1a;跳过reshape直接置信度筛选 优化2&#xff1a;减少用于nms的bbox数 3.举个荔枝 总结 前言 减少YOLO后处理nms的计算和比较次数。 YOLO-det…

一 初识爬虫

一 爬虫和python 二 爬虫的合法性 三 爬虫的介绍 通过程序去访问网站&#xff0c;网站肯定希望用户来访问网站&#xff0c;而不是程序来访问&#xff0c;可以使用一些技术手段。设置障碍。 越过障碍。 四 爬虫示例 需求:用程序模拟浏览器。输入一个网址。从该网址中获取到资源或…

从短视频到AIGC,快手字节重开一局

作者 | 辰纹 来源 | 洞见新研社 从短视频到剪辑工具&#xff0c;从电商到外卖&#xff0c;再到如今的AIGC大模型&#xff0c;快手和字节的竞争从来就没有停止过。 通用大模型方面&#xff0c;快手有快意&#xff0c;字节有豆包&#xff1b;AI图片创作快手有可图&#xff0c;…

docker续3:

一、使用Dockerfile创建应用镜像 在Docker file中定义所需要执⾏的指令&#xff0c;使⽤ docker build创建镜像&#xff0c;过程中会按照dockerfile所定义的内容进⾏打开临时性容器&#xff0c;把docker file中命令全部执⾏完成&#xff0c;就得到了⼀个容器应⽤镜像&#xff…

星河社区升级命令行工具,一站式完成大模型实训

飞桨PFCC社区成员卢畅贡献。卢畅&#xff0c;飞桨 PFCC 成员&#xff0c;飞桨开源之星&#xff0c;飞桨开发者专家&#xff08;PPDE&#xff09;&#xff0c;长期参加飞桨黑客松、护航计划等开源活动&#xff0c;参与过飞桨执行器预分析性能优化、静态图自动并行架构升级等任务…

SpringBoot项目整合智谱AI + SSE推送流式数据到前端展示 + RxJava得浅显理解

项目背景&#xff1a; 项目背景是一个这个AI答题应用平台&#xff0c;我引入AI得作用就是让AI根据我指定得这个题目的标题和描述来生成一些列的题目。&#xff08;主要功能是这个&#xff0c;但是还用了AI给我评分&#xff0c;不过这个功能比较简单&#xff0c;在本文就简单介…

python可视化-条形图

1、加载数据 import pandas as pd import seaborn as sns import matplotlib.pyplot as plt# 导入数据 df pd.read_csv(E:/workspace/dataset/seaborn-data-master/tips.csv) df.head()2、基于seaborn的条形图 # 利用barplot函数快速绘制 sns.barplot(x"total_bill&quo…

Python从0到100(五十三):机器学习-决策树及决策树分类器

前言: 零基础学Python:Python从0到100最新最全教程。 想做这件事情很久了,这次我更新了自己所写过的所有博客,汇集成了Python从0到100,共一百节课,帮助大家一个月时间里从零基础到学习Python基础语法、Python爬虫、Web开发、 计算机视觉、机器学习、神经网络以及人工智能…

中微8S6990 EEPROM踩坑记录

中微8S6990 EEPROM内容丢失解决记录 问题描述: 问题程序如下: void temp_remember(uint16_t temperature,uint16_t address_H,uint16_t address_L) {uint8_t temp,temp1 0;temp temperature>>8;temp1 temperature;FLASH_UnLock();FLASH_Erase_DataArea(address_H);…

虹科方案 | 领航智能交通革新:虹科PEAK智行定位车控系统Demo版亮相

导读&#xff1a; 在智能汽车技术发展浪潮中&#xff0c;车辆控制系统的智能化、网络化已成为行业发展的必然趋势。虹科PEAK智行定位车控系统&#xff0c;集成了尖端科技&#xff0c;能够实现车辆全方位监控与控制的先进系统。从实时GPS定位到CAN/CANFD信号处理&#xff0c;虹科…