Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 的WPF事件触发器_C#_Wpf_Xaml_Triggers_Eventtrigger - Fatal编程技术网

C# 的WPF事件触发器

C# 的WPF事件触发器,c#,wpf,xaml,triggers,eventtrigger,C#,Wpf,Xaml,Triggers,Eventtrigger,我有一个WPF网格,我想在值更改时突出显示一个单元格。这确实适用于下面的EventTrigger,但在加载窗口时会高亮显示每个单元格。是否有一种“更好”的WPF方法仅在设置初始值或加载窗口后触发 <Style TargetType="DataGridCell" x:Key="FlashStyle"> <Style.Triggers> <EventTrigger RoutedEvent="Binding.TargetUpdated">

我有一个WPF
网格
,我想在值更改时突出显示一个单元格。这确实适用于下面的
EventTrigger
,但在加载窗口时会高亮显示每个单元格。是否有一种“更好”的WPF方法仅在设置初始值或加载窗口后触发

<Style TargetType="DataGridCell" x:Key="FlashStyle">
    <Style.Triggers>
        <EventTrigger RoutedEvent="Binding.TargetUpdated">
                <BeginStoryboard>
                    <Storyboard x:Name="Blink" AutoReverse="True">
                        <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)">
                            <EasingColorKeyFrame KeyTime="00:00:01" Value="Red" />
                        </ColorAnimationUsingKeyFrames>
                    </Storyboard>
                </BeginStoryboard>
        </EventTrigger>
    </Style.Triggers>
</Style>

正如我承诺的那样,我重新审视了这个答案,并给出了一个例子。我发现我的原始答案无法工作,因为无法在运行时修改触发器集合。还有另一个解决方案,我将在这里解释

最新答案 由于我们无法在运行时更改触发器集合,因此我看到了两个可能的选项:

  • 制作一个智能事件触发器,它将知道如何处理第一个
    TargetUpdated
    事件并忽略它
  • 创建我们自己的新附加事件,使EventTrigger处理该事件,并仅在我们希望触发EventTrigger时(即每次更新目标时,第一次除外)引发该事件
  • 第一个选项可以使用。我还没试过,但这可能是一个好办法

    第二个选项相当简单,如下所示:

    public class AfterLoadBehavior
    {
        #region TargetUpdatedAfterLoad Attached Event
    
        public static readonly RoutedEvent TargetUpdatedAfterLoadEvent = EventManager.RegisterRoutedEvent(
            "TargetUpdatedAfterLoad", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AfterLoadBehavior));
    
        public static void AddNeedsCleaningHandler(DependencyObject d, RoutedEventHandler handler)
        {
            UIElement uiElement = d as UIElement;
            if (uiElement != null)
            {
                uiElement.AddHandler(TargetUpdatedAfterLoadEvent, handler);
            }
        }
    
        public static void RemoveNeedsCleaningHandler(DependencyObject d, RoutedEventHandler handler)
        {
            UIElement uiElement = d as UIElement;
            if (uiElement != null)
            {
                uiElement.RemoveHandler(TargetUpdatedAfterLoadEvent, handler);
            }
        }
    
        #endregion
    
        #region RaiseTargetUpdatedAfterLoadEvent Attached Property
    
        public static bool GetRaiseTargetUpdatedAfterLoadEvent(FrameworkElement obj)
        {
            return (bool)obj.GetValue(RaiseTargetUpdatedAfterLoadEventProperty);
        }
    
        public static void SetRaiseTargetUpdatedAfterLoadEvent(FrameworkElement obj, bool value)
        {
            obj.SetValue(RaiseTargetUpdatedAfterLoadEventProperty, value);
        }
    
        public static readonly DependencyProperty RaiseTargetUpdatedAfterLoadEventProperty =
            DependencyProperty.RegisterAttached("RaiseTargetUpdatedAfterLoadEvent", typeof(bool), typeof(AfterLoadBehavior),
            new PropertyMetadata(false, OnRaiseTargetUpdatedAfterLoadEventChanged));
    
        private static void OnRaiseTargetUpdatedAfterLoadEventChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var frameworkElement = (FrameworkElement)d;
            frameworkElement.AddHandler(Binding.TargetUpdatedEvent, new RoutedEventHandler((sender, args) =>
                {
                    if (GetIsFirstValueChange(frameworkElement))
                    {
                        SetIsFirstValueChange(frameworkElement, false);
                        return;
                    }
    
                    frameworkElement.RaiseEvent(new RoutedEventArgs(AfterLoadBehavior.TargetUpdatedAfterLoadEvent));
                }));
        }
    
        #endregion
    
        #region IsFirstValueChange Attached Property
    
        public static bool GetIsFirstValueChange(FrameworkElement obj)
        {
            return (bool)obj.GetValue(IsFirstValueChangeProperty);
        }
    
        public static void SetIsFirstValueChange(FrameworkElement obj, bool value)
        {
            obj.SetValue(IsFirstValueChangeProperty, value);
        }
    
        public static readonly DependencyProperty IsFirstValueChangeProperty =
            DependencyProperty.RegisterAttached("IsFirstValueChange", typeof(bool), typeof(AfterLoadBehavior),
            new PropertyMetadata(true));
    
        #endregion
    }
    
    使用此选项,您需要修改样式,如下所示:

    <Style TargetType="DataGridCell" x:Key="FlashStyle">
        <Setter Property="local:AfterLoadBehavior.RaiseTargetUpdatedAfterLoadEvent" Value="True" />
        <Style.Triggers>
            <EventTrigger RoutedEvent="{x:Static local:AfterLoadBehavior.TargetUpdatedAfterLoadEvent}">
                    <BeginStoryboard>
                        <Storyboard x:Name="Blink" AutoReverse="True">
                            <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)">
                                <EasingColorKeyFrame KeyTime="00:00:01" Value="Red" />
                            </ColorAnimationUsingKeyFrames>
                        </Storyboard>
                    </BeginStoryboard>
            </EventTrigger>
        </Style.Triggers>
    </Style>
    
    
    
    此行为的作用是注册到
    Binding.TargetUpdated
    事件,并在第一次调用它时忽略它。对于其他时间,它会引发新创建的
    targetUpdateAfterLoadEvent
    ,该事件由
    EventTrigger
    处理

    所以它比我最初预期的要复杂一些,但是这里没有什么疯狂的事情发生,一旦你把这个行为添加到你的代码中,它就很容易使用了。 希望这有帮助


    原始答案(无效)
    我不知道有什么简单的XAML专用解决方案可以解决这个问题,但您可以编写一个附加属性,它将注册到DataGridCell的
    Loaded
    事件,并且只在事件触发器加载后添加它。

    这听起来不必要复杂,我希望有一个优雅的解决方案:)代码方面,这是一个非常简单的解决方案,可以在5分钟内编码。稍后我会尝试用一个例子更新我的答案。非常好,没有我想的那么复杂!谢谢你的邀请,阿迪