首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WPF EventTrigger

WPF EventTrigger
EN

Stack Overflow用户
提问于 2014-05-14 13:49:29
回答 1查看 1.9K关注 0票数 3

我有一个WPF Grid,当一个值发生变化时,我想突出显示一个单元格。这确实适用于下面的EventTrigger,但是在加载窗口时突出显示每个单元格。是否有一种“更好”的WPF方式只在设置初始值或加载窗口之后触发?

代码语言:javascript
复制
<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>
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-05-14 13:58:13

正如我所承诺的,我已经重新讨论了这个答案,并给出了一个例子。我发现我原来的答案无法工作,因为不可能在运行时修改触发器集合。不过,还有另一种解决办法,我将在此解释。

更新答复

由于我们无法在运行时对触发器集合进行更改,我看到了两个可能的选项:

  1. 创建一个智能EventTrigger,它将知道如何处理第一个TargetUpdated事件并忽略它。
  2. 创建我们自己的新附加事件,让EventTrigger处理它,并且只在我们希望EventTrigger触发时才引发它,也就是说,每次除了第一次更新目标时,都会引发它。

第一个选项可以通过使用TriggerBase实现。我还没试过,但这可能是个好方法。

第二种选择相当简单,并在此提供:

代码语言:javascript
复制
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
}

使用此方法,您需要修改样式如下:

代码语言:javascript
复制
<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事件,并在第一次调用它时忽略它。在其他情况下,它会引发新创建的TargetUpdatedAfterLoadEvent,它由您的EventTrigger处理。

因此,结果比我原先预期的要复杂一些,但是这里并没有什么疯狂的事情发生,一旦将这种行为添加到代码中,就很容易使用。希望这能有所帮助。

原来的答案(不起作用)

我不知道这是一个简单的XAML解决方案,但是您可以编写一个附加属性,它将注册到DataGridCell的Loaded事件,并且只在加载事件触发器之后添加。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23656577

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档