WPF:自定义路由事件的实现

路由事件通过EventManager,RegisterRoutedEvent方法注册,通过AddHandler和RemoveHandler来关联和解除关联的事件处理函数;通过RaiseEvent方法来触发事件;通过传统的CLR事件来封装后供用户使用。

如何实现自定义路由事件,可以参考MSDN官网上的文档:如何:创建自定义路由事件

下面的这个demo参考自<葵花宝典--WPF自学手册>。

1、MainWindow.xaml

 1 <Window x:Class="WpfApplication1.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:sys="clr-namespace:System;assembly=mscorlib"
 5         xmlns:local="clr-namespace:WpfApplication1"
 6         Title="MainWindow" Height="518" Width="525"
 7         local:MySimpleButton.CustomClick="InsertList"
 8         Loaded="Window_Loaded">
 9     <Grid  Name="grid1" local:MySimpleButton.CustomClick="InsertList">
10         <Grid.RowDefinitions>
11             <RowDefinition Height="Auto"></RowDefinition>
12             <RowDefinition Height="*"></RowDefinition>
13             <RowDefinition Height="Auto"></RowDefinition>
14             <RowDefinition Height="Auto"></RowDefinition>
15
16         </Grid.RowDefinitions>
17         <local:MySimpleButton x:Name="simpleBtn" CustomClick="InsertList" >
18             MySimpleBtn
19         </local:MySimpleButton>
20         <ListBox Name="lstMsg" Grid.Row="1"></ListBox>
21         <CheckBox Grid.Row="2" Name="chkHandle">Handle first event</CheckBox>
22         <Button Grid.Row="3" Click="cmdClear_Click">Clear list</Button>
23     </Grid>
24
25 </Window>

在xaml文件中,完成页面的元素布局之后,给几个元素添加了事件处理函数。

(1)给Window添加了Loaded事件的处理函数,还添加了MySimpleButton的CustomClick事件的类事件处理函数

1 local:MySimpleButton.CustomClick="InsertList"
2 Loaded="Window_Loaded"

(2)给Grid同样添加了MySimpleButton的类事件处理函数

(3)给MySimpleButton元素添加了CustomClick事件的实例事件处理函数

CustomClick="InsertList" 

(4)给Button元素添加了Click事件处理函数

Click="cmdClear_Click"

2、MySimpleButton.cs

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Windows.Controls;
 7 using System.Windows;
 8
 9 namespace WpfApplication1
10 {
11     //继承Button类,自定义一个名为MySimpleButton的Button
12     public class MySimpleButton:Button
13     {
14         //———————————类事件处理函数————————————
15         static MySimpleButton()
16         {
17             //为路由事件CustomClickEvent注册一个类事件处理函数
18             //类事件处理函数的优先权高于实例事件处理函数
19             EventManager.RegisterClassHandler(typeof(MySimpleButton), CustomClickEvent, new RoutedEventHandler(CustomClickClassHandler), false);
20         }
21         //创建一个名为CustomClickClassHandler的类事件处理函数
22         //为了通知外部窗口,把路由事件的信息输出,需要添加一个普通的CLR事件ClassHandlerProcessed
23         public event EventHandler ClassHandlerProcessed;
24         public static void CustomClickClassHandler(object sender, RoutedEventArgs e)
25         {
26             MySimpleButton simpleBtn = sender as MySimpleButton;
27             EventArgs args = new EventArgs();
28             simpleBtn.ClassHandlerProcessed(simpleBtn, args);
29         }
30
31         //———————————实例事件处理函数————————————
32         //创建和注册一个名为CustomClickEvent的路由事件,路由策略为Bubble
33         public static readonly RoutedEvent CustomClickEvent = EventManager.RegisterRoutedEvent("CustomClick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MySimpleButton));
34         //给路由事件添加一个CLR事件包装器
35         public event RoutedEventHandler CustomClick
36         {
37             add
38             {
39                 AddHandler(CustomClickEvent, value);
40             }
41             remove
42             {
43                 RemoveHandler(CustomClickEvent, value);
44             }
45         }
46         //RaiseEvent()触发CustomClickEvent事件
47         protected override void OnClick()
48         {
49             RaiseCustomClickEvent();
50         }
51         void RaiseCustomClickEvent()
52         {
53             RoutedEventArgs newEventArgs = new RoutedEventArgs(MySimpleButton.CustomClickEvent);
54             RaiseEvent(newEventArgs);
55         }
56
57     }
58 }

这个是自定义的一个按钮类,在里面创建了自定义的路由事件。

3、MainWindow.xaml.cs

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Windows;
 7 using System.Windows.Controls;
 8 using System.Windows.Data;
 9 using System.Windows.Documents;
10 using System.Windows.Input;
11 using System.Windows.Media;
12 using System.Windows.Media.Imaging;
13 using System.Windows.Navigation;
14 using System.Windows.Shapes;
15
16 namespace WpfApplication1
17 {
18     /// <summary>
19     /// Interaction logic for MainWindow.xaml
20     /// </summary>
21     public partial class MainWindow : Window
22     {
23         public MainWindow()
24         {
25             InitializeComponent();
26             //MySimpleButton的类事件处理函数处理过,window就能得到通知
27             this.simpleBtn.ClassHandlerProcessed += new EventHandler(simpleBtn_RaisedClass);
28         }
29         protected int eventCount = 0;
30         //CusomClick的事件处理函数
31         private void InsertList(object sender, RoutedEventArgs e)
32         {
33             eventCount++;
34             string msg = "#" + eventCount.ToString() + ":\r\n" + "InsertList\r\n" + "Sender:" + sender.ToString() + "\r\n Source:" + e.Source+"\r\n"+"Original Source:"+e.OriginalSource;
35             lstMsg.Items.Add(msg);
36             //CheckBox选中状态表示路由事件是否已处理,若已处理,则不在传递
37             e.Handled = (bool)chkHandle.IsChecked;
38         }
39         //类事件处理函数已经完成,打印信息
40         private void simpleBtn_RaisedClass(object sender, EventArgs e)
41         {
42             eventCount++;
43             string msg = "#" + eventCount.ToString() + ":\r\n WindowClassHandler\r\nSender:" + sender.ToString();
44             lstMsg.Items.Add(msg);
45         }
46         //Clear列表内容
47         private void cmdClear_Click(object sender, RoutedEventArgs e)
48         {
49             eventCount = 0;
50             lstMsg.Items.Clear();
51         }
52         //在window的Load事件中给Grid另外添加一个名为ProcessHandlersToo的路由事件处理函数
53         //通过这种方式添加,即使路由事件被标记"已处理",处理函数仍然会执行
54         private void Window_Loaded(object sender, RoutedEventArgs e)
55         {
56             grid1.AddHandler(MySimpleButton.CustomClickEvent, new RoutedEventHandler(ProcessHandlerToo), true);
57         }
58
59         private void ProcessHandlerToo(object sender, RoutedEventArgs e)
60         {
61             eventCount++;
62             string msg = "#" + eventCount.ToString() + ":\r\n" + "InsertList\r\n" + "Sender:" + sender.ToString() + "\r\n Source:" + e.Source + "\r\n" + "Original Source:" + e.OriginalSource;
63             lstMsg.Items.Add(msg);
64
65         }
66     }
67 }

上面是路由事件的具体处理。

4、运行效果

从上面的运行效果可以看到,

(1)CheckBox未选中

路由事件在传递时,首先被类事件处理函数处理,然后沿着视觉树向上传递(MySimpleButton-->Grid-->Window),依次被添加了实例事件处理函数的元素进行事件处理。在传到Grid元素时,先进行InserList处理,再进行ProcessHandlerToo处理,这两个事件处理函数是用不同方式添加的,执行顺序不同。

(2)CheckBox选中

选中了CheckBox,则路由事件传递到MySimpleButton元素并进行处理后,被标记成"已处理",则之后不再向上传递,Grid和Window元素不再执行InsertList,但是Grid中的处理函数ProcessHandlerToo仍然会执行,这是两种事件添加方式不同的地方。

时间: 2024-08-28 15:38:01

WPF:自定义路由事件的实现的相关文章

WPF自定义路由事件

一 概要 本文通过实例演示WPF自定义路由事件的使用,进而探讨了路由事件与普通的CLR事件的区别(注:"普通的CLR事件"这个说法可能不太专业,但是,我暂时也找不到什么更好的称呼,就这么着吧,呵呵.)(扩展阅读:例说.NET事件的使用). 二 实例演示与说明 1 新建DetailReportEventArgs类,该类派生自RoutedEventArgs类,RoutedEventArgs类包含与路由事件相关的状态信息和事件数据.DetailReportEventArgs类中定义了属性Ev

WPF自定义路由事件(二)

WPF中的路由事件 as U know,和以前Windows消息事件区别不再多讲,这篇博文中,将首先回顾下WPF内置的路由事件的用法,然后在此基础上自定义一个路由事件. 1.WPF内置路由事件 WPF中的大多数事件都是路由事件,WPF有3中路由策略: 具体不多讲,单需要注意的是WPF路由事件是沿着VIsualTree传递的.VisualTree与LogicalTree的区别在于:LogicalTree的叶子节点是构成用户界面的控件(xaml紧密相关),而VisualTree要连控件中的细微结构也

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

原文:WPF的路由事件.冒泡事件.隧道事件(预览事件) 本文摘要: 1:什么是路由事件: 2:中断事件路由: 3:自定义路由事件: 4:为什么需要自定义路由事件: 5:什么是冒泡事件和预览事件(隧道事件): 1:什么是路由事件 WPF中的事件为路由事件,所谓路由事件,MSDN定义如下: 功能定义:路由事件是一种可以针对元素树中的多个侦听器(而不是仅针对引发该事件的对象)调用处理程序的事件. 实现定义:路由事件是一个 CLR 事件,可以由 RoutedEvent 类的实例提供支持并由 Window

迟到的 WPF 学习 —— 路由事件

1. 理解路由事件:WPF 通过事件路由(event routing)概念增强了传统的事件执行的能力和范围,允许源自某个元素的事件由另一个元素引发,例如,事件路由允许工具栏上的一个按钮点击的事件在被代码处理之前上传到工具栏,再由工具栏上传到所属窗体 2. 定义.注册和包装路由事件:和依赖性属性类似,它由只读的静态字段表示,在一个静态构造函数中注册,并通过一个标准的 .Net 事件定义进行包装.如 Button 的 Click 事件,该事件继承自抽象的 ButtonBase 基类 public a

自定义路由事件

自定义路由事件大体上可分为三个步骤: 1.声明并注册路由事件: 2.为路由事件添加CLR事件包装: 3.创建可以激发路由事件的方法. 主要的示例代码如下: public class TimeButton : Button { /// <summary> /// 声明并注册路由事件. /// </summary> public static readonly RoutedEvent ReportTimeEvent = EventManager.RegisterRoutedEvent(

WPF中路由事件的传播

路由事件(RoutedEvent)是WPF中新增的事件,使用起来与传统的事件差别不大, 但传播方式是完全不同的. 路由事件的传播方式 通过RoutingStrategy来定义传播的方式 public enum RoutingStrategy { Tunnel = 0, //隧道,由顶层元素向内传播,事件一般以Preview开头 Bubble = 1, //冒泡,与隧道相反,向外传播 Direct = 2, //直接,与传统的事件相似 } WPF中的路由事件用的最多的就是Tunnel和Bubble

学习WPF——了解路由事件

入门 我们先来看一个例子 前台代码: 后台代码: 点击按钮的运行效果第一个弹出窗口 第二个弹出窗口: 第三个弹出窗口: 说明 当点击按钮之后,先触发按钮的click事件,再上查找,发现stackpanel也注册了该事件,那么接着触发StackPanel的Button.Click事件,依次再触发Grid的Button.Click事件,这就是最基本的事件路由,事件路由的策略是右内向外的 如果不希望在XAML中注册路由事件,那么也可以通过编码的方式注册路由事件如下所示 如果想终止事件的向上传递,可以使

WPF 添加自定义路由事件

给button  Btn添加自定义的路由事件Backdoor; Btn.AddHandler(Button.MouseUpEvent, new RoutedEventHandler(Backdoor), true); 版权声明:本文为博主原创文章,未经博主允许不得转载.

WPF Demo18 路由事件

using System.Windows; namespace 路由事件2 { public class Student { ////声明并定义路由事件 //public static readonly RoutedEvent NameChangedEvent = // EventManager.RegisterRoutedEvent("NameChanged", // RoutingStrategy.Bubble, // typeof(RoutedEventHandler), //