gpt4 book ai didi

c# - WPF 事件触发器

转载 作者:行者123 更新时间:2023-11-30 16:11:56 26 4
gpt4 key购买 nike

我有一个 WPF Grid,我想在值更改时突出显示一个单元格。这确实适用于下面的 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>

最佳答案

正如所 promise 的那样,我重新审视了这个答案来举个例子。我发现我的原始答案不起作用,因为无法在运行时修改触发器集合。还有另一种解决方案,我将在此处进行解释。

更新的答案

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

  1. 制作一个知道如何处理第一个 TargetUpdated 的智能 EventTrigger事件并忽略它。
  2. 创建我们自己的新附加事件,让 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事件,并且只会在加载后添加事件触发器。

关于c# - WPF 事件触发器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23656577/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com