WPF快速指导10:WPF中的事件及冒泡事件和隧道事件(预览事件)的区别

 

WPF快速指导10:WPF中的事件及冒泡事件和隧道事件(预览事件)的区别

本文摘要:

1:什么是路由事件;

2:中断事件路由;

3:自定义路由事件;

4:为什么需要自定义路由事件;

5:什么是冒泡事件和预览事件(隧道事件);

1:什么是路由事件

WPF中的事件为路由事件,所谓路由事件,MSDN定义如下:

功能定义:路由事件是一种可以针对元素树中的多个侦听器(而不是仅针对引发该事件的对象)调用处理程序的事件。

实现定义:路由事件是一个 CLR 事件,可以由 RoutedEvent 类的实例提供支持并由 Windows Presentation Foundation (WPF) 事件系统来处理。

但这两类定义都比较抽象,我们来看更具体的定义:

  1. <Border Height="50" Width="250" BorderBrush="Gray" BorderThickness="1" >
  2. <StackPanel Background="LightGray" Orientation="Horizontal" MouseUp="StackPanel_MouseUp">
  3. <TextBlock Name="YesTB" Width="50" MouseUp="YesTB_MouseUp" Background="Blue" >Yes</TextBlock>
  4. </StackPanel>
  5. </Border>

在这个例子中,事件的事件路由为:

TextBlock -->StackPanel-->Border —>...

2:中断事件路由      所有的路由事件都共享一个公共的事件数据基类 RoutedEventArgsRoutedEventArgs 定义了一个采用布尔值的 Handled 属性。 Handled 属性的目的在于,允许路由中的任何事件处理程序通过将 Handled 的值设置为 true 来将路由事件标记为“已处理”。

  1. private void StackPanel_MouseUp(object sender, MouseButtonEventArgs e)
  2. {
  3. MessageBox.Show("Panel");
  4. }
  5.  
  6. private void YesTB_MouseUp(object sender, MouseButtonEventArgs e)
  7. {
  8. MessageBox.Show("button");
  9. e.Handled = true;
  10. }

在上面的例子中,将不再触发StackPanel_MouseUp事件。

3:自定义路由事件

如下面的示例所示,首先使用 RegisterRoutedEvent 方法注册一个 RoutedEvent。按照约定,RoutedEvent 静态字段名称应当以后缀 Event 结束。在本示例中,事件的名称是 Tap,事件的路由策略是 Bubble。在注册调用之后,可以为该事件提供添加和移除公共语言运行时 (CLR) 事件访问器。

请注意,尽管该事件在本特定示例中是通过 OnTap 虚方法引发的,但您引发事件的方式或者事件响应更改的方式取决于您的需要。

还要注意,本示例主要实现 Button 的一整个子类;该子类是作为单独的程序集构建的,之后将在单独的可扩展应用程序标记语言 (XAML) 页上实例化为一个自定义类。这是为了说明这样一个概念:创建子类的控件可以插入到由其他控件组成的树中,在这种情况下,这些控件上的自定义事件具有与任何固有的 Windows Presentation Foundation (WPF) 元素完全相同的事件路由功能。

  1. public class MyButtonSimple: Button
  2. {
  3. // Create a custom routed event by first registering a RoutedEventID
  4. // This event uses the bubbling routing strategy
  5. public static readonly RoutedEvent TapEvent = EventManager.RegisterRoutedEvent(
  6. "Tap", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyButtonSimple));
  7.  
  8. // Provide CLR accessors for the event
  9. public event RoutedEventHandler Tap
  10. {
  11. add { AddHandler(TapEvent, value); }
  12. remove { RemoveHandler(TapEvent, value); }
  13. }
  14.  
  15. // This method raises the Tap event
  16. void RaiseTapEvent()
  17. {
  18. RoutedEventArgs newEventArgs = new RoutedEventArgs(MyButtonSimple.TapEvent);
  19. RaiseEvent(newEventArgs);
  20. }
  21. // For demonstration purposes we raise the event when the MyButtonSimple is clicked
  22. protected override void OnClick()
  23. {
  24. RaiseTapEvent();
  25. }
  26.  
  27. }
  1. <Window
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. xmlns:custom="clr-namespace:SDKSample;assembly=SDKSampleLibrary"
  5. x:Class="SDKSample.RoutedEventCustomApp"
  6.  
  7. >
  8. <Window.Resources>
  9. <Style TargetType="{x:Type custom:MyButtonSimple}">
  10. <Setter Property="Height" Value="20"/>
  11. <Setter Property="Width" Value="250"/>
  12. <Setter Property="HorizontalAlignment" Value="Left"/>
  13. <Setter Property="Background" Value="#808080"/>
  14. </Style>
  15. </Window.Resources>
  16. <StackPanel Background="LightGray">
  17. <custom:MyButtonSimple Name="mybtnsimple" Tap="TapHandler">Click to see Tap custom event work</custom:MyButtonSimple>
  18. </StackPanel>
  19. </Window>

4:为什么需要自定义路由事件

一直到目前看来,我们都不太需要自定义的路由事件。但是,在我们创建自定义控制的时候,创建一些和业务相关的路由事件,就显得很有必要。

如,创建一个在线考试中的题型展示控件,可以为该控件设计一个自定义事件,为“提交”。这样一来,这个题型控件不仅仅只有一些通用事件,还可以看上去更“业务”。

5:什么是冒泡事件和预览事件(隧道事件)

 路由事件实际上分两类:冒泡事件和预览事件(隧道事件)。上文中的例子就是冒泡事件。

冒泡事件是WPF路由事件中最为常见,它表示事件从源元素扩散(传播)到可视树,直到它被处理或到达根元素。这样您就可以针对源元素的上方层级对象处理事件。例如,您可向嵌入的 Grid 元素附加一个 Button.Click 处理程序,而不是直接将其附加到按钮本身。气泡事件有指示其操作的名称(例如,MouseDown)。

隧道事件采用另一种方式,从根元素开始,向下遍历元素树,直到被处理或到达事件的源元素。这样上游元素就可以在事件到达源元素之前先行截取并进行处理。根据命名惯例,隧道事件带有前缀 Preview(例如 PreviewMouseDown)。

在本文一开始的例子中,如果我们将MouseUP,改为PreviewMouseUP,效果会如何呢。

区别:

冒泡事件:在YesTB上点击,首先弹出“button”,再弹出“panel”。

预览事件(隧道事件)事件:在YesTB上点击,首先弹出“panel”,再弹出“button”。

看到了这点区别,那么我们加入e.Handled=true的时机也要不同。首先,

冒泡事件例子中:e.Handled=true加在YesTB_PreviewMouseUp中,加入后,点击YesTB,将只弹出“button”。

预览事件(隧道事件)例子中:e.Handled=true家在StackPanel_PreviewMouseUp中,加入后,点击YesTB,将只弹出“panel”。

WPF中的事件及冒泡事件和隧道事件(预览事件)的区别的更多相关文章

  1. WPF的路由事件、冒泡事件、隧道事件(预览事件)

    本文摘要: 1:什么是路由事件: 2:中断事件路由: 3:自定义路由事件: 4:为什么需要自定义路由事件: 5:什么是冒泡事件和预览事件(隧道事件): 1:什么是路由事件 WPF中的事件为路由事件,所 ...

  2. iOS全埋点解决方案-界面预览事件

    前言 ​ 我们先了解 UIViewController 生命周期相关的内容和 iOS 的"黑魔法" Method Swizzling.然后再了解页面浏览事件($AppViewScr ...

  3. Winforn中使用FastReport实现点击导出按钮PDF预览并弹出另存为对话框

    场景 FastReport安装包下载.安装.去除使用限制以及工具箱中添加控件: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/10 ...

  4. vue开发中vue-resource + canvas 图片压缩、上传、预览

    1.使用vue-resource上传,也可以自定义ajax上传: 2.使用<input type="file" @change="submit()" na ...

  5. WPF教程六:理解WPF中的隧道路由和冒泡路由事件

    WPF中使用路由事件升级了传统应用开发中的事件,在WPF中使用路由事件能更好的处理事件相关的逻辑,我们从这篇开始整理事件的用法和什么是直接路由,什么是冒泡路由,以及什么是隧道路由. 事件最基本的用法 ...

  6. WPF中MVVM模式下控件自有的事件绑定

    1.原因 在WPF中单纯的命令绑定往往不能满足覆盖所有的事件,例如ComboBox的SelectionChanged事件,DataGrid的SelectionChanged事件等等,这时就可以用事件绑 ...

  7. 前端(十五)—— JavaScript事件:绑定事件方式、事件的冒泡和默认事件、鼠标事件、键盘事件、表单 事件、文档事件、图片事件、页面事件

    JS事件:绑定事件方式.事件的冒泡和默认事件.鼠标事件.键盘事件.表单 事件.文档事件.图片事件.页面事件 一.事件的两种绑定方式 1.on事件绑定方式 document.onclick = func ...

  8. 搞清Image加载事件(onload)、加载状态(complete)后,实现图片的本地预览,并自适应于父元素内(完成)

    onload与complete介绍 complete只是HTMLImageElement对象的一个属性,可以判断图片加载完成,不管图片是不是有缓存:而onload则是这个Image对象的load事件回 ...

  9. 用WPF实现打印及打印预览

    原文:用WPF实现打印及打印预览 应该说,WPF极大地简化了我们的打印输出工作,想过去使用VC++做开发的时候,打印及预览可是一件极麻烦的事情,而现在我不会再使用C++来做Windows的桌面应用了- ...

随机推荐

  1. MySQL中自增长与锁

    在InnoDB存储引擎中,对于每个含有自增长值的表都有一个自增长计数器(auto-increment counter)当对含有自增长的计数器的表进行插入操作时,这个计数器会被初始化,执行如下的语句可以 ...

  2. Python3.6全栈开发实例[011]

    11.元素分类有如下值li= [11,22,33,44,55,66,77,88,99,90],将所有大于 66 的值保存至字典的第一个key中,将小于 66 的值保存至第二个key的值中.即: {'k ...

  3. 1、hive安装详细步骤

    一.环境准备 hadoop-2.7.2 java 1.7.0 apache-hive-1.2.1 mysql Hive配置文件介绍 •hive-site.xml      hive的配置文件 •hiv ...

  4. nodejs从服务器获取数据

    // 从服务器获取数据 request('http://192.168.1.7:8080/getDemo', function(error, response, body) { console.log ...

  5. 《Python机器学习》笔记(五)

    通过降维压缩数据 在前面已经介绍了几种不同的特征选择技术对数据集进行降维的方法.另一种常用于降维的特征选择方法就是特征抽取.数据压缩也是机器学习领域中的一个重要内容.数据压缩技术可以帮助我们对数据及逆 ...

  6. 升级到tomcat8遇到The method getDispatcherType() is undefined for the type HttpServletRequest

    今天升级到tomcat8,发现原来的项目不能运行了,遇到下面的错误:The method getDispatcherType() is undefined for the type HttpServl ...

  7. 动手动脑:String.equals()的使用方法

    public class StringEquals { /** * @param args the command line arguments */ public static void main( ...

  8. Understanding When to use RabbitMQ or Apache Kafka

    https://content.pivotal.io/rabbitmq/understanding-when-to-use-rabbitmq-or-apache-kafka How do humans ...

  9. jQuery中的部分方法

    1.empty() – jQuery 文档操作 从被选元素移除所有内容,包括所有文本和子节点. 用法:$(selector).empty(); 其中,selector可以是"#id" ...

  10. SpringBoot整合集成redis

    Redis安装:https://www.cnblogs.com/zwcry/p/9505949.html 1.pom.xml <project xmlns="http://maven. ...