首页 > 其他分享 >WPF 自定义路由事件的实现

WPF 自定义路由事件的实现

时间:2024-08-27 14:39:10浏览次数:12  
标签:事件处理 自定义 System 事件 using WPF MySimpleButton 路由

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

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

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

1、MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="518" Width="525"
        local:MySimpleButton.CustomClick="InsertList"
        Loaded="Window_Loaded">
    <Grid  Name="grid1" local:MySimpleButton.CustomClick="InsertList">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>

        </Grid.RowDefinitions>
        <local:MySimpleButton x:Name="simpleBtn" CustomClick="InsertList" >
            MySimpleBtn
        </local:MySimpleButton>
        <ListBox Name="lstMsg" Grid.Row="1"></ListBox>
        <CheckBox Grid.Row="2" Name="chkHandle">Handle first event</CheckBox>
        <Button Grid.Row="3" Click="cmdClear_Click">Clear list</Button>
    </Grid>

</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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows;

namespace WpfApplication1
{
    //继承Button类,自定义一个名为MySimpleButton的Button
    public class MySimpleButton:Button
    {
        //———————————类事件处理函数————————————
        static MySimpleButton()
        {
            //为路由事件CustomClickEvent注册一个类事件处理函数
            //类事件处理函数的优先权高于实例事件处理函数
            EventManager.RegisterClassHandler(typeof(MySimpleButton), CustomClickEvent, new RoutedEventHandler(CustomClickClassHandler), false);
        }
        //创建一个名为CustomClickClassHandler的类事件处理函数
        //为了通知外部窗口,把路由事件的信息输出,需要添加一个普通的CLR事件ClassHandlerProcessed
        public event EventHandler ClassHandlerProcessed;
        public static void CustomClickClassHandler(object sender, RoutedEventArgs e)
        {
            MySimpleButton simpleBtn = sender as MySimpleButton;
            EventArgs args = new EventArgs();
            simpleBtn.ClassHandlerProcessed(simpleBtn, args);
        }

        //———————————实例事件处理函数————————————
        //创建和注册一个名为CustomClickEvent的路由事件,路由策略为Bubble
        public static readonly RoutedEvent CustomClickEvent = EventManager.RegisterRoutedEvent("CustomClick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MySimpleButton));
        //给路由事件添加一个CLR事件包装器
        public event RoutedEventHandler CustomClick
        {
            add
            {
                AddHandler(CustomClickEvent, value);
            }
            remove
            {
                RemoveHandler(CustomClickEvent, value);
            }
        }
        //RaiseEvent()触发CustomClickEvent事件
        protected override void OnClick()
        {
            RaiseCustomClickEvent();
        }
        void RaiseCustomClickEvent()
        {
            RoutedEventArgs newEventArgs = new RoutedEventArgs(MySimpleButton.CustomClickEvent);
            RaiseEvent(newEventArgs);
        }

    }
}

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

3、MainWindow.xaml.cs

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.Navigation;
using System.Windows.Shapes;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            //MySimpleButton的类事件处理函数处理过,window就能得到通知
            this.simpleBtn.ClassHandlerProcessed += new EventHandler(simpleBtn_RaisedClass);
        }
        protected int eventCount = 0;
        //CusomClick的事件处理函数
        private void InsertList(object sender, RoutedEventArgs e)
        {
            eventCount++;
            string msg = "#" + eventCount.ToString() + ":\r\n" + "InsertList\r\n" + "Sender:" + sender.ToString() + "\r\n Source:" + e.Source+"\r\n"+"Original Source:"+e.OriginalSource;
            lstMsg.Items.Add(msg);
            //CheckBox选中状态表示路由事件是否已处理,若已处理,则不在传递
            e.Handled = (bool)chkHandle.IsChecked;
        }
        //类事件处理函数已经完成,打印信息
        private void simpleBtn_RaisedClass(object sender, EventArgs e)
        {
            eventCount++;
            string msg = "#" + eventCount.ToString() + ":\r\n WindowClassHandler\r\nSender:" + sender.ToString();
            lstMsg.Items.Add(msg);
        }
        //Clear列表内容
        private void cmdClear_Click(object sender, RoutedEventArgs e)
        {
            eventCount = 0;
            lstMsg.Items.Clear();
        }
        //在window的Load事件中给Grid另外添加一个名为ProcessHandlersToo的路由事件处理函数
        //通过这种方式添加,即使路由事件被标记"已处理",处理函数仍然会执行
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            grid1.AddHandler(MySimpleButton.CustomClickEvent, new RoutedEventHandler(ProcessHandlerToo), true);
        }

        private void ProcessHandlerToo(object sender, RoutedEventArgs e)
        {
            eventCount++;
            string msg = "#" + eventCount.ToString() + ":\r\n" + "InsertList\r\n" + "Sender:" + sender.ToString() + "\r\n Source:" + e.Source + "\r\n" + "Original Source:" + e.OriginalSource;
            lstMsg.Items.Add(msg);

        }
    }
}

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

4、运行效果

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

(1)CheckBox未选中

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

(2)CheckBox选中

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

来源:https://www.cnblogs.com/tt2015-sz/p/4746997.html

 

标签:事件处理,自定义,System,事件,using,WPF,MySimpleButton,路由
From: https://www.cnblogs.com/ywtssydm/p/18382628

相关文章

  • WPF 数据校验
    一、新建NameValidationRule类publicclassNameValidationRule:ValidationRule{publicoverrideValidationResultValidate(objectvalue,CultureInfocultureInfo){varlength=value.ToString().Length;if(length......
  • WPF C# split picture into small pieces and show in grid cells
    usingSystem;usingSystem.Collections.Generic;usingSystem.Drawing;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;usingSystem.Windows;usingSystem.Windows.Controls;usingSystem.Windows.Data;usingSystem.Windows.Documents;using......
  • nuxt3项目自定义环境变量,typescript全局提示
    最近使用nuxt3框架来写项目,其中有一点就是typescript语法提示让人闹心,使用vscode编辑器,如果有语法提示进行编码,工作效率可以提升一个档次。本篇文章说的就是如何在vscode中使用nuxt3框架,自定义环境变量,支持typescript语法提示。列出当前使用的环境版本node#21.4.0......
  • 使用xinference部署自定义embedding模型(docker)
    使用xinference部署自定义embedding模型(docker)说明:首次发表日期:2024-08-27官方文档:https://inference.readthedocs.io/zh-cn/latest/index.html使用docker部署xinferenceFROMnvcr.io/nvidia/pytorch:23.10-py3#KeepsPythonfromgenerating.pycfilesinthecontai......
  • WPF 模板
    一、数据模板继承了ItemConrol的控件对象(如ListView、ListBox、DataGrid、TabControl等等),都可以使用数据模板DataTemplate。数据模板的作用在于决定每个Item中的数据的展示形式。普通控件通过Template属性来定义模板,而子项容器控件则通过ItemTemplate属性来定义子项模板。先创......
  • 新手专科准大一学习c语言的第10天之strcpy、memset、自定义函数的学习与应用
    strcpystrcpy是C语言标准库中的一个字符串操作函数,用于将源字符串复制到目标字符串中。#include<stdio.h>#include<string.h>intmain(){chararr1[50];//确保目标数组足够大,能够容纳源字符串chararr2[]="helloworld";//源字符串......
  • WPF中如何根据数据类型使用不同的数据模板
    我们在将一个数据集合绑定到列表控件时,有时候想根据不同的数据类型,显示为不同的效果。例如将一个文件夹集合绑定到ListBox时,系统文件夹显示为不同的效果,就可以使用模板选择器功能。WPF提供了一个模板选择器类型DataTemplateSelector,它可以根据数据对象和数据绑定元素来选择 Dat......
  • 学懂C++(四十四):C++ 自定义内存管理的深入解析:内存池与自定义分配器
    目录1.内存池(MemoryPool)概念模型特点核心点实现适用场景经典示例实现代码解析2.自定义分配器(CustomAllocators)概念模型特点核心点实现适用场景经典示例实现代码解析高级自定义分配器示例代码解析总结        C++作为一种高性能编程语言,在......
  • Vue-cil(脚手架,版本:2.6.10)的搭建过程(项目创建,组件路由)
    目录一.前端项目结构的对比  1.传统的前端项目结构  2.现在的前端项目结构 二.什么是vue-cil三.主要的功能四.需要的环境(前提)  1.Node.js  2.npm  3.使用HbuilderX快速搭建​五.常用命令六.创建项目的需要  1.创建组件      ......
  • WPF 路由事件
    一、什么是路由事件?根据MSDN定义:功能定义:路由事件是一种可以针对元素树中的多个侦听器(而不是仅针对引发该事件的对象)调用处理程序的事件。实现定义:路由事件是由类的实例支持的CLR事件,RoutedEvent由事件WindowsPresentationFoundation(WPF)系统处理。典型的WPF应......