为啥 IsMouseOver 被识别而 MouseDown 不是(Wpf 样式触发器)?

Posted

技术标签:

【中文标题】为啥 IsMouseOver 被识别而 MouseDown 不是(Wpf 样式触发器)?【英文标题】:Why IsMouseOver is recognized and MouseDown isn't (Wpf Style trigger)?为什么 IsMouseOver 被识别而 MouseDown 不是(Wpf 样式触发器)? 【发布时间】:2012-05-26 21:48:07 【问题描述】:

为什么 IsMouseOver 被识别为 WPF 样式触发器而 MouseDown 不是 - 假设两者都是有效的 UIElement 属性,如 seen here-。第一个触发器运行良好,但第二个触发器甚至无法编译。

<Style.Triggers>
    <Trigger Property="IsMouseOver" Value="true">
        <Setter Property="OpacityMask">
            <Setter.Value>
                <LinearGradientBrush >
                    <GradientStop Color="Transparent" Offset="0"/>
                    <GradientStop Color="Black" Offset="0.5"/>
                    <GradientStop Color="Transparent" Offset="1"/>
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
    </Trigger>
    <Trigger Property="MouseDown" Value="true">
        <Setter Property="OpacityMask">
            <Setter.Value>
                <LinearGradientBrush>
                    <GradientStop Color="Black" Offset="0" />
                    <GradientStop Color="White" Offset="1" />
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
    </Trigger>
</Style.Triggers>

【问题讨论】:

不知道,但MouseDown 并未在您提供的链接中列为属性。 OnMouseDown() 被列为响应事件而调用的方法,而不是属性。 【参考方案1】:

好吧,我猜你把MouseDown 事件误认为是财产。没有IsMouseDown 属性,但存在类似的IsPressed 属性,但仅适用于继承ButtonBase 的类。如果您想保持代码隐藏干净,您应该只在代码隐藏中使用事件或编写附加属性。

这就是你的做法。创建类:

using System;
using System.Windows;

namespace Mrpyo

    public static class MouseDownHelper 
    
        public static readonly DependencyProperty IsEnabledProperty = DependencyProperty.RegisterAttached("IsEnabled", 
        typeof(bool), typeof(MouseDownHelper), new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnNotifyPropertyChanged)));

        public static void SetIsEnabled(UIElement element, bool value)
        
            element.SetValue(IsEnabledProperty, value);
        

        public static bool GetIsEnabled(UIElement element)
        
            return (bool)element.GetValue(IsEnabledProperty);
        

        private static void OnNotifyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        
            var element = d as UIElement;
            if (element != null && e.NewValue != null)
            
                if ((bool)e.NewValue)
                
                    Register(element);
                
                else
                
                    UnRegister(element);
                
             
        

        private static void Register(UIElement element)
        
            element.PreviewMouseDown += element_MouseDown;
            element.PreviewMouseLeftButtonDown += element_MouseLeftButtonDown;
            element.MouseLeave += element_MouseLeave;
            element.PreviewMouseUp += element_MouseUp;
        

        private static void UnRegister(UIElement element)
        
            element.PreviewMouseDown -= element_MouseDown;
            element.PreviewMouseLeftButtonDown -= element_MouseLeftButtonDown;
            element.MouseLeave -= element_MouseLeave;
            element.PreviewMouseUp -= element_MouseUp;
        

        private static void element_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        
            var element = sender as UIElement;
            if (element != null)
            
                SetIsMouseDown(element, true);
            
        

        private static void element_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        
            var element = sender as UIElement;
            if (element != null)
            
                SetIsMouseLeftButtonDown(element, true);
            
        

        private static void element_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
        
            var element = sender as UIElement;
            if (element != null)
            
                SetIsMouseDown(element, false);
                SetIsMouseLeftButtonDown(element, false);
            
        

        private static void element_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        
            var element = sender as UIElement;
            if (element != null)
            
                SetIsMouseDown(element, false);
                SetIsMouseLeftButtonDown(element, false);
            
        

        internal static readonly DependencyPropertyKey IsMouseDownPropertyKey = DependencyProperty.RegisterAttachedReadOnly("IsMouseDown",
        typeof(bool), typeof(MouseDownHelper), new FrameworkPropertyMetadata(false));
        public static readonly DependencyProperty IsMouseDownProperty = IsMouseDownPropertyKey.DependencyProperty;

        internal static void SetIsMouseDown(UIElement element, bool value)
        
            element.SetValue(IsMouseDownPropertyKey, value);
        

        public static bool GetIsMouseDown(UIElement element)
        
            return (bool)element.GetValue(IsMouseDownProperty);
        

        internal static readonly DependencyPropertyKey IsMouseLeftButtonDownPropertyKey = DependencyProperty.RegisterAttachedReadOnly("IsMouseLeftButtonDown",
        typeof(bool), typeof(MouseDownHelper), new FrameworkPropertyMetadata(false));
        public static readonly DependencyProperty IsMouseLeftButtonDownProperty = IsMouseLeftButtonDownPropertyKey.DependencyProperty;

        internal static void SetIsMouseLeftButtonDown(UIElement element, bool value)
        
            element.SetValue(IsMouseLeftButtonDownPropertyKey, value);
        

        public static bool GetIsMouseLeftButtonDown(UIElement element)
        
            return (bool)element.GetValue(IsMouseLeftButtonDownProperty);
        
    

然后按照你的风格:

<Setter Property="local:MouseDownHelper.IsEnabled" Value="True"/>
<Style.Triggers>
    <Trigger Property="local:MouseDownHelper.IsMouseLeftButtonDown" Value="True">
        <!-- ... -->
    </Trigger>
</Style.Triggers>

当然还要在你的 XAML 文件中添加命名空间(查看顶部):

xmlns:local="clr-namespace:Mrpyo"

【讨论】:

你能举个例子说明你所说的“写一个附加的属性”吗? 非常感谢这堂课。我不得不使用 PreviewMouseDown 和 PreviewMouseUp 事件来让它工作,但在那之后它很棒。 IsPressed 是完全正确的方法,如果你正在设计一个按钮。 @mrpyo 我正在使用您的解决方案(是的,即使在今天 :D )但它不起作用,没有错误,但什么也没做。我在一个滑块的拇指矩形上使用它。我错过了什么? @agiro 您是否尝试过像 Robert Gowland 推荐的那样使用 PreviewMouseDown 和 PreviewMouseUp(我编辑了答案)?另请记住,如果您有硬编码值,则触发器将不起作用:social.msdn.microsoft.com/Forums/vstudio/en-US/…【参考方案2】:

您可以在Style.Triggers 中使用MouseDown Event,但您必须为此使用EventTrigger。

<EventTrigger RoutedEvent="MouseEnter">
    <BeginStoryboard>
        <Storyboard>
            ...
        </Storyboard>
    </BeginStoryboard>
</EventTrigger>

记住这一点

一旦条件引发事件,该操作将不会被撤消 不再是真的。

【讨论】:

【参考方案3】:

您可以在使用 Control.Triggers 时使用 PreviewMouseLeftButtonDown,将控件替换为正在使用模板的控件项:

<Grid>
  <Grid.Triggers>
    <EventTrigger RoutedEvent="Grid.PreviewMouseLeftButtonDown">
      <BeginStoryboard>
        <Storyboard>
          ...
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Grid.Triggers>
</Grid>

【讨论】:

以上是关于为啥 IsMouseOver 被识别而 MouseDown 不是(Wpf 样式触发器)?的主要内容,如果未能解决你的问题,请参考以下文章

vb用mouse_event模拟鼠标双击为啥没有效果?

嘿,他们为啥不被识别

有些日期被识别为日期,有些日期不被识别。为啥?

从一个网页复制的东西 粘贴单另一个网页为啥粘贴不全 例如:Reacts with: Rat Predicted: Human, Mouse

第一次提问:为啥'py'被识别但'python'不被识别?在终端中运行的快捷方式? 'echo %PATH%' 给出巨大的路径?

为啥我的 @Aspect 无法被我的 SpringBoot 应用程序识别?