我有一个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事件,并且仅在事件触发器加载后才添加.