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)双击文本框

相关推荐
玖笙&2 小时前
✨WPF编程进阶【9.1】:WPF资源完全指南(附源码)
c++·c#·wpf·visual studio
想你依然心痛2 小时前
HarmonyOS 6(API 23)分布式实战:基于悬浮导航与沉浸光感的“光影协创“跨设备白板系统
分布式·wpf·harmonyos·悬浮导航·沉浸光感
c#上位机2 天前
wpf路由事件
wpf
nashane2 天前
HarmonyOS 鸿蒙 2026 全栈实战:从手势驱动到分布式数据落地的完整架构
wpf·harmony app
秋雨雁南飞2 天前
WPF 国际化(全球化)管理
wpf
nashane3 天前
HarmonyOS 6.0 分布式数据库进阶:设备协同与高效数据同步实战(API 11 Stage 模型)
wpf·harmonyos 5
极客智造3 天前
WPF InputBindings MVVM详解
wpf
nashane3 天前
HarmonyOS 6.0 分布式数据实战:KVStore跨设备同步与高性能查询指南(API 11 Stage模型)
wpf·harmonyos 5
SEO-狼术4 天前
Easily Reorder Rows in WPF Grids
wpf