​    这节讲一下WPF中的路由事件(Routed Event)

【什么是事件】

在了解路由事件前,我们应先来了解一下什么是事件(Event)

在Windows系统中,像鼠标单击,双击,移动这样的,都是在触发着一个个事件,事件代表着用户在Windows上的一个动作,相当于用户给系统交代了一个任务让它去执行。本质上事件就是条信息数据,这条数据有对事件的描述,以及携带着事件的参数,这些参数可以看做是事件的“Metadata”,比如你点击鼠标左键,会触发MouseLeftDown和MouseLeftUp这两个事件,它们的参数中就携带了鼠标在屏幕的点击位置(X,Y值)等等信息。

我们回到编程概念中,在事件这个模型中,我们要理解以下三个跟事件有关的抽象:

  • 事件的拥有者:事件的拥有者就是事件的触发者,比如按钮被点击,那么按钮就是事件的拥有者;

  • 事件的响应者:事件的响应者就是事件的处理者,比如我们在winform后置代码中声明的一个一个事件处理方法,拥有事件处理方法的from体就是事件的响应者;

  • 事件订阅关系:要想一个事件被处理,需要让事件的响应者去订阅事件拥有者的事件,在winfrom中这一操作被具象化为在“小闪电”操作栏中对对应的事件关联上后置代码中的事件处理器。

    如果说事件的拥有者和响应者是河的两岸,那事件的订阅关系就是连接两岸的桥,让事件的 拥有者通过桥把事件数据交代给事件的响应者,而桥并不是唯一的,事件的订阅可以是多个,它是一对n(n>=0)的关系。

当然,上述事件模型也有其弊端:

  • 事件的响应者必须要显式订阅事件才能生效

  • 事件的拥有者必须能访问到事件的响应者,这样才能建立订阅关系

所以我们能了解到,原始的事件模型,对于订阅关系的建立有严格的要求,因此,微软在WPF中推出了路由事件,它使得事件可以不再以订阅关系建立,下面来了解一下。

【路由事件】

  提到路由事件,首先一点,什么是路由呢?这里引入《深入浅出WPF》一书中对路由的解释:“起点与终点间有若干个中转站,从起点出发后经过每个中转站时要做出选择,最终以正确(比如最短或者最快)的路径到达终点。” 路由描述的就是这样的一个过程。

路由事件,是指事件的拥有者和响应者不必建立订阅关系,拥有者只管激发事件,响应者通过在自身设置事件监听器去监听对应的事件,并可以决定事件是否继续传播,如果说原始事件是两个人窃窃私语的话,那路由事件就是一队人挨个传话。当事件响应者通过事件监听器监听到某个事件的发生,通过事件携带的参数可以获取到事件的来源,从而做出判断该事件是否是自己关心的某个控件激发的,如果是,可以处理并停止事件的传播,如果不是,则放行不予理睬。

请设想如下图所示的一个XAML控件层级关系:

蓝色代表Window控件,其内部有两个按钮和一个Grid布局,按钮2在Grid布局中,当按钮1激发单击事件后,该事件的传播路径为:

  按钮1-->Window

当按钮2激发单击事件后,该事件的传播路径为:

  按钮2-->Grid-->Window

【如何使用路由事件】

  下面来学习一下如何使用事件监听器监听路由事件,请看如下代码:

XAML页面结构是名为grid的Grid布局中有个点击按钮。我们在后置代码中使用AddHandler方法设置事件监听器,该方法的第一个参数是指定监听的路由事件类型对象,第二个参数是指定事件处理器,处理器方法由RoutedEventHandler对象包装,当按钮点击时,在输出窗口中输出了“监听到了btn_click的事件”字样。此处要注意,跟原始事件处理器不同的是,路由事件处理器的第一个参数sender,是监听事件的控件对象在此处就是grid对象,而我们要获取是谁激发的事件则是根据第二个参数e的OriginalSource属性。

当我们捕获到关心的事件时,控制事件不再继续传播该怎么做呢,事件处理器的第二个参数e有个Handled属性,该属性是个bool值,设置其为true即可。

当然,事件监听器也可以从XAML代码中指定:

通过为ButtonBase(Button的父类)的Click路由事件处理器绑定方法,来实现单击事件的监听。从ButtonBase源代码中可以找到如下图所示的路由事件处理器,该类型跟AddHandler方法的第二个参数类型一致。

WPF路由事件的更多相关文章

  1. WPF自学入门(三)WPF路由事件之内置路由事件

    有没有想过在.NET中已经有了事件机制,为什么在WPF中不直接使用.NET事件要加入路由事件来取代事件呢?最直观的原因就是典型的WPF应用程序使用很多元素关联和组合起来,是否还记得在WPF自学入门(一 ...

  2. WPF路由事件二:路由事件的三种策略

    一.什么是路由事件 路由事件是一种可以针对元素树中的多个侦听器而不是仅仅针对引发该事件的对象调用处理程序的事件.路由事件是一个CLR事件. 路由事件与一般事件的区别在于:路由事件是一种用于元素树的事件 ...

  3. WPF 路由事件 Event Routing

    原文:WPF 路由事件 Event Routing 1.路由事件介绍 之前介绍了WPF的新的依赖属性系统,本篇将介绍更高级的路由事件,替换了之前的.net普通事件.相比.net的事件,路由事件具有更强 ...

  4. WPF 路由事件总结

    1.什么是路由事件 已下为MSDN中的定义 功能定义:路由事件是一种可以针对元素树中的多个侦听器(而不是仅针对引发该事件的对象)调用处理程序的事件. 实现定义:路由事件是一个 CLR 事件,可以由 R ...

  5. .NET: WPF 路由事件

    (一)使用WPF内置路由事件 xaml: <Window x:Class="WpfApplication1.MainWindow" xmlns="http://sc ...

  6. WPF自学入门(四)WPF路由事件之自定义路由事件

    在上一遍博文中写到了内置路由事件,其实除了内置的路由事件,我们也可以进行自定义路由事件.接下来我们一起来看一下WPF中的自定义路由事件怎么进行创建吧. 创建自定义路由事件分为3个步骤: 1.声明并注册 ...

  7. WPF路由事件三:自定义路由事件

    与依赖项属性类似,WPF也为路由事件提供了WPF事件系统这一组成.为一个类型添加一个路由事件的方式与为类型添加依赖项属性的方法类似,添加一个自定义路由事件的步骤: 一.声明路由事件变量并注册:定义只读 ...

  8. WPF路由事件学习(一)

    路由事件与一般事件的区别在于:路由事件是一种用于元素树的事件,当路由事件触发后,它可以向上或向下遍历可视树和逻辑树,他用一种简单而持久的方式在每个元素上触发,而不需要任何定制的代码(如果用传统的方式实 ...

  9. WPF 路由事件

    最近想封装一个关于手势的控件,但是由其他的控件覆盖之后发现不能触发,据说是有一些事件在定义的时候就处理过e.Handle了. 定义的时候就处理了,就是为了控件能够正常的工作,别如Button.Mous ...

随机推荐

  1. Python开发篇——构建虚拟Python开发环境(Conda+Poetry)

    前言 之前虽略有提及Python,但是没有实际地写点料.惭愧,惭愧,所以这次先起个头,讲讲如何构建虚拟Python开发环境.相信之前看过我博客的人可能会想:博主不会又要聊聊Docker吧?放心,不会. ...

  2. Guava - Set集合

    当我们在统计一个字符串中每个单词出现的次数时,通常的做法是分割字符串,遍历字符串,然后放到一个map里面,来进行统计,Guava中提供了类似功能的集合,Multiset String strWorld ...

  3. jvm源码解读--12 invokspecial指令的解读

    先看代码 package com.zyt.jvmbook; public class Girl extends Person{ public Girl() { int a; } @Override p ...

  4. Vue项目发布的问题--http://localhost:8088/static/fonts/fontawesome-webfont.af7ae50.woff2

    问题:ngnix将8080转成80对外访问,找不对woff2等文件 一\ 搭建环境 ngnix-->conf中 server { listen 80; server_name 10.9.240. ...

  5. WCF简单Demo

    WCF,光看书的原理,稍微有点枯燥,通过自己动手,会更容易理解契约声明,面向服务,分布式等概念. 1.创建WCF服务. 2.WcfService1.CS中声明新的契约. namespace WcfSe ...

  6. DOS命令--Windows操作系统之母

    DOS命令 DOS是什么 解释:Disk Operating System的缩写,意思是"磁盘操作系统" 系统:DOS就是人给机器下达命令的集合,是存储在操作系统中的命令集 基本用 ...

  7. CF559B Equivalent Strings TJ

    前言 题目传送门 正解:模拟,递归. 考试的 T4,还是想复杂了 qwq. 这题不要用 STL,容易 \(\texttt{TLE}\)!! 题意简述 翻译够简了. 对了给一下样例解释的翻译: 第一个样 ...

  8. RHCE_DAY03

    shell函数 在shell环境中,将一些需要重复使用的操作,定义为公共的语句块,即可称为函数(给一堆命令取一个别名) 函数可以使脚本中的代码更加简洁,增强易读性,提高脚本的执行效率 #函数定义格式1 ...

  9. python+pycharm+selenium+谷歌浏览器驱动 自动化环境部署(一)

    准备工作: 第一步:安装python.打开网址https://www.python.org/downloads/windows/     现在最新版本3.7,本人使用的是3.6. 第二步:安装pych ...

  10. 用传纸条讲 HTTPS

    我和小宇早恋了,上课的时候老说话. 老师把我们的座位分得很远,我在第一排,她在最后一排,我们中间隔了很多人. 但我们还是想通过传纸条的方式交流. 我们中间的那些同学,虽然坏心思比较多,但好在可以保证将 ...