作为承诺,我重新审视了这个答案并给出了一个示例。我发现我的原始答案无法工作,因为不可能在运行时修改触发器集合。但是有另一种解决方案,我将在这里解释。
更新的答案
既然我们无法在运行时更改触发器集合,我看到两个可能的选项:
1.创建一个智能EventTrigger,它将知道如何处理第一个TargetUpdated事件并忽略它。
2.创建我们自己的新附加事件,使EventTrigger处理它,并仅在我们希望EventTrigger触发时引发它,即每次更新目标除第一次之外。
第一种选项可能可以通过使用
Blend SDK和从TriggerBase 继承来实现。我没有尝试过,但这可能是一个不错的选择。
第二个选项相当简单,并在此处提供:
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
事件,并且仅在加载完成后添加事件触发器。