• 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() + ":
    " + "InsertList
    " + "Sender:" + sender.ToString() + "
     Source:" + e.Source+"
    "+"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() + ":
     WindowClassHandler
    Sender:" + 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() + ":
    " + "InsertList
    " + "Sender:" + sender.ToString() + "
     Source:" + e.Source + "
    " + "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仍然会执行,这是两种事件添加方式不同的地方。

  • 相关阅读:
    关于数据库的压测(window+liunx)
    参数化关联----三种方式
    jmeter的使用
    day07----------移动端测试
    day07----------Charles抓取web端的HTTPS协议下载和七个功能操作
    CURL 运用
    有关数据库的导出导入备份
    同时删除多张表的数据
    一条sql语句update 多条记录
    linux 将一个服务器上的文件或文件夹拷贝到另一个服务器上(转载)
  • 原文地址:https://www.cnblogs.com/tt2015-sz/p/4746997.html
Copyright © 2020-2023  润新知