编程语言
首页 > 编程语言> > C#-WPF EventTrigger用于

C#-WPF EventTrigger用于

作者:互联网

我有一个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>

解决方法:

按照承诺,我将重新讨论该示例.我发现我的原始答案无法正常工作,因为无法在运行时修改触发器集合.我将在这里解释另一种解决方案.

更新的答案

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

>创建一个智能的EventTrigger,它将知道如何处理第一个TargetUpdated事件并忽略它.
>创建我们自己的新附加事件,让EventTrigger处理它,并仅在我们希望EventTrigger触发时(即,除了第一次以外,每次更新目标时)触发它.

第一个选项可以通过使用Blend SDK and inheriting from TriggerBase<T>来实现.我还没有尝试过,但这可能是一个不错的选择.

第二个选项相当简单,并在此处提供:

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事件,并在第一次调用该事件时将其忽略.在其他情况下,它将引发新创建的TargetUpdatedAfterLoadEvent,由EventTrigger处理.

因此,事实证明它比我最初预期的要复杂一些,但是这里没有发生任何疯狂的事情,一旦将此行为添加到代码中,它就非常易于使用.
希望这可以帮助.

原始答案(无效)

我不知道有一个简单的仅针对XAML的解决方案,但是您可以编写一个附加属性,该属性将注册到DataGridCell的Loaded事件,并且仅在事件触发器加载后才添加.

标签:eventtrigger,wpf,xaml,c,triggers
来源: https://codeday.me/bug/20191121/2054048.html