wpf附加事件

附加事件的作用让一个非UI元素的静态类(如Mouse),能够定义一种"可以借给任何UI元素使用"的路由事件

1、定义附加事件的静态类

1)定义附加事件

下面的代码中 EventManager.RegisterRoutedEvent方法注册路由事件,该方法第一个参数是"事件名称";第二个参数是路由策略,路由策略分为冒泡、隧道、直接三种;第3个参数是委托类型,这个委托类型不是固定的,RoutedEventHandler是标准的写法;第4个参数是事件所在的类。

2)定义附加属性

这里定义一个附加属性IsEnabled,附加属性的作用就是启动附加事件,在附加属性的回调函数中,动态订阅/取消订阅附加事件,本文代码中当IsEnabled为true时,监听MouseDoubleClick 事件,并在监听方法Element_MouseDoubleClick中触发附加事件。

csharp 复制代码
 public static class DoubleClickHelper
    {
        // ========== 第一部分:定义附加事件 ==========
        public static readonly RoutedEvent DoubleClickEvent =
            EventManager.RegisterRoutedEvent("DoubleClick", RoutingStrategy.Bubble,
                typeof(RoutedEventHandler), typeof(DoubleClickHelper));

        public static void AddDoubleClickHandler(DependencyObject obj, RoutedEventHandler handler)
        {
            (obj as UIElement)?.AddHandler(DoubleClickEvent, handler);
        }

        public static void RemoveDoubleClickHandler(DependencyObject obj, RoutedEventHandler handler)
        {
            (obj as UIElement)?.RemoveHandler(DoubleClickEvent, handler);
        }

        // ========== 第二部分:附加属性来启用功能 ==========
        public static readonly DependencyProperty IsEnabledProperty =
            DependencyProperty.RegisterAttached(
                "IsEnabled",                // 属性名
                typeof(bool),               // 类型
                typeof(DoubleClickHelper),  // 所属类
                new PropertyMetadata(false, OnIsEnabledChanged)); // 值改变时的回调

        // 设置 IsEnabled 属性
        public static void SetIsEnabled(DependencyObject obj, bool value)
        {
            obj.SetValue(IsEnabledProperty, value);
        }

        // 获取 IsEnabled 属性
        public static bool GetIsEnabled(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsEnabledProperty);
        }

        // ========== 第三部分:当启用时,监听鼠标双击 ==========
        private static void OnIsEnabledChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            Control element = obj as Control;
            if (element == null) return;

            if ((bool)e.NewValue == true)
            {
                // 启用:监听鼠标双击
                element.MouseDoubleClick += Element_MouseDoubleClick;
            }
            else
            {
                // 禁用:取消监听
                element.MouseDoubleClick -= Element_MouseDoubleClick;
            }
        }

        // ========== 第四部分:双击发生时,触发我们的附加事件 ==========
        private static void Element_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            UIElement element = sender as UIElement;
            if (element == null) return;
            // 触发附加事件!
            RoutedEventArgs args = new RoutedEventArgs(DoubleClickEvent, element);
            element.RaiseEvent(args);
        }
    }

2、xaml代码

为控件添加附加事件的监控,在xaml使用类名.附加事件名

csharp 复制代码
    <StackPanel Margin="20"  local:DoubleClickHelper.IsEnabled="True"
                local:DoubleClickHelper.DoubleClick="OnDoubleClick">
            <!-- 按钮1:启用双击功能 -->
            <Button Content="按钮1 - 双击我" 
                local:DoubleClickHelper.IsEnabled="True"
                local:DoubleClickHelper.DoubleClick="OnDoubleClick"
                Height="50" Margin="0,5"/>
            <!-- 按钮2:也启用双击功能 -->
            <Button Content="按钮2 - 双击我" 
                local:DoubleClickHelper.IsEnabled="True"
                local:DoubleClickHelper.DoubleClick="OnDoubleClick"
                Height="50" Margin="0,5"/>
            <!-- 文本框:也支持双击 -->
            <TextBox Text="文本框 - 双击我" 
                 local:DoubleClickHelper.IsEnabled="True"
                 local:DoubleClickHelper.DoubleClick="OnDoubleClick"
                 Height="30" Margin="0,5"/>
            <!-- 状态显示 -->
            <RichTextBox Name="StatusText" Margin="0,20" 
                   Foreground="Red" FontSize="12"/>
        </StackPanel>

3、逻辑层代码

只要附加事件被触发,下面的代码就会执行,如果判断被双击的是Button则获取Button的Content属性,如果被双击的是TextBox则获取它的Text属性。

csharp 复制代码
 private void OnDoubleClick(object sender, RoutedEventArgs e)
        {
            // sender 是被双击的那个元素
            FrameworkElement element = sender as FrameworkElement;
            string elementType = element?.GetType().Name ?? "未知";
            string content = "";

            // 获取显示文本
            if (element is Button btn)
                content = btn.Content.ToString();
            else if (element is TextBox txt)
                content = txt.Text;

            // 显示提示
            StatusText.AppendText (  $"双击了 {elementType}:{content},时间:{System.DateTime.Now:T}"+Environment.NewLine );
        }

4、测试结果

1)双击按钮1

你会发现有richTextbox有两条记录,一个是按钮1被双击了,一个是StackPanel,这是因为附加是冒泡事件,当按钮1被双击以后,冒泡基制也会导致StackPanel作为按钮1的父控件也可以监听到双击事件。

2)双击文本框

相关推荐
故渊at10 小时前
第二板块:Android 四大组件标准化学理 | 第十二篇:四大组件全景总结与系统服务(System Server)架构
android·架构·wpf·四大组件·system service
伶俜6613 小时前
# [特殊字符] 零基础学 ArkUI 数据持久化(专题三):5 种存储方案深度对比
学习·华为·wpf·harmonyos
IT策士13 小时前
Redis 从入门到精通:数据结构String 与键管理
数据结构·redis·wpf
AC赳赳老秦14 小时前
技术文章素材收集自动化:用 OpenClaw 自动爬取行业资讯、技术热点、优质文章
运维·开发语言·python·自动化·wpf·deepseek·openclaw
加号314 小时前
【WPF】 Storyboard 故事板动画设计深度解析
wpf
xiaoshuaishuai815 小时前
C# Avalonia 依赖属性与WPF的区别
开发语言·c#·wpf
大G的笔记本1 天前
生产级 Spring Boot 网关简单实现方案
wpf
稷下元歌3 天前
七天学会plc加机器视觉之AI 接入 外设模块开发全详细操作文档(全程配套视频按文档实操)
python·sql·qt·贪心算法·r语言·wpf·时序数据库
happyprince3 天前
11-Hugging Face Transformers 分布式与并行系统深度分析
分布式·c#·wpf
加号33 天前
【WPF】 基于 Canvas 读取并渲染 DXF 文件的技术指南
c#·wpf