gpt4 book ai didi

.net - 在 WPF 中定义多个时 DataTrigger 不触发

转载 作者:行者123 更新时间:2023-12-01 12:37:17 24 4
gpt4 key购买 nike

我遇到了一个 WPF 问题,我无法解决,而且我已经发布了很多 stackoverflow 帖子,但都没有运气,所以我想我会看看是否有人可以提供帮助

我只是想让我的 DataGrid 的单元格背景根据值是上升还是下降来脉动两种颜色中的一种

我尝试使用 EventTrigger NotifyOnTargetUpdated 并绑定(bind)背景颜色,但不允许绑定(bind)到 Storyboard中的属性背景

然后我尝试将 DataTriggers 与状态字段一起使用,“U”表示向上,“D”表示向下。我在每个更新周期开始时将状态重置为“N”(更新受到限制),起初,每个场景都有 2 个 DataTriggers,看起来一切正常。我同时看到了绿色和红色动画,但后来我注意到有更新发生但没有更新。一旦更新通过,似乎只有首先声明的 DataTrigger 才真正起作用,在极少数情况下没有出现第一个条件时,另一个触发器会触发。为了检验这个理论是否正确,我首先运行了每个条件,正如预期的那样,在每种情况下,第一个声明的触发器只会触发 90% 的时间。

我到处搜索试图找到这种异常的原因,但没有运气,如果有人能阐明如何解决这个问题,甚至可能以更可靠的方式实现相同的功能,我将不胜感激。

 <DataGridTextColumn Header="Last Trade" Width="60" Binding="{Binding last_trade}" IsReadOnly="true">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=last_trade_state}" Value="D">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color" Duration="00:00:01" From="LightSalmon" To="Transparent"></ColorAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>

<DataTrigger Binding="{Binding Path=last_trade_state}" Value="U">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color" Duration="00:00:01" From="LightGreen" To="Transparent"></ColorAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>

</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>

最佳答案

诊断

首先让我介绍一下我认为的MCVE说明问题:

<Grid Background="CornflowerBlue">
<CheckBox x:Name="_CheckBox" Content="Toggle me" />
<Grid.Style>
<Style TargetType="Grid">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=_CheckBox}" Value="False">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color" Duration="00:00:01" From="LightSalmon" To="Transparent" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding IsChecked, ElementName=_CheckBox}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color" Duration="00:00:01" From="LightGreen" To="Transparent" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>

加载 Grid 时,我们会看到一个红色闪烁,表明触发了第一个触发器 - 这是预期的行为。如果我们随后检查 CheckBox,我们会看到一个绿色的闪光,这意味着第二个触发器被触发了——再次,正如预期的那样。但这就是问题所在 - 如果我们取消选中 CheckBox,我们将不再看到红色闪光。事实上,从现在开始,我们只会在选中时看到绿色闪烁,而在取消选中 CheckBox 时不会看到红色闪烁。如果我们对触发器重新排序,情况是对称的。

这种行为的原因归结为两个事实:

  1. 动画一旦启动,不会自动停止(默认情况下 - 请参阅进一步说明)
  2. 如果我们在一个已经设置动画的属性上应用一个动画,它不会停止/删除之前的动画,而是将它添加到该属性的动画列表中——在我们的例子中,最后添加的动画覆盖了由前一个,但情况可能并非总是如此1

当动画到达其持续时间结束时会发生什么由 FillBehavior 属性控制,该属性有两个值 - HoldEndStop ,默认值为 HoldEnd。所以在我们的例子中,当任一动画完成时,它都会保持背景 Transparent。它与实际透明的背景一致 - 如果背景没有动画,它将变回 CornflowerBlue

鉴于我们对观察到的行为有解释 - 第一个红色动画可见,因为绿色动画尚未开始。但是一旦是,当我们取消选中 CheckBox 时,红色动画会重新启动,但我们看不到它的效果,因为它们被保持背景 Transparent 的绿色动画覆盖了.至少这是一个可行的逻辑模型——也许框架足够聪明,不会在它们的效果无论如何都会被忽略时不启动动画,并且红色动画实际上并没有重新启动。

半解

下一个合乎逻辑的步骤是在我们的动画上设置 FillBehavior=Stop。这让我们接近我们的目标,但还不够。除了这两个异常(exception),一切看起来都很好:

  1. 一旦动画结束,背景将返回到 CornflowerBlue - 这可能不是所需的行为
  2. 如果我们在绿色动画仍在运行时取消选中 CheckBox,它不会立即停止,而是会结束,然后我们才能看到红色动画的剩余部分

解决方案

当检查或未选中复选框时,我们真正想做的是在运行时流产当前动画并将其替换为另一个动画。为此,我们可以命名 BeginStoryboard 元素并使用 StopStoryboard 元素中止当前动画:

<Grid Background="CornflowerBlue">
<CheckBox x:Name="_CheckBox" Content="Toggle me" />
<Grid.Style>
<Style TargetType="Grid">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=_CheckBox}" Value="False">
<DataTrigger.EnterActions>
<StopStoryboard BeginStoryboardName="Storyboard2" />
<BeginStoryboard Name="Storyboard1">
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color" Duration="00:00:01" From="LightSalmon" To="Transparent" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding IsChecked, ElementName=_CheckBox}" Value="True">
<DataTrigger.EnterActions>
<StopStoryboard BeginStoryboardName="Storyboard1" />
<BeginStoryboard Name="Storyboard2">
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color" Duration="00:00:01" From="LightGreen" To="Transparent" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>

FillBehavior=Stop 的使用是可选的,它只会控制背景是否返回到 CornflowerBlue

1 我刚刚确认事实上并非总是如此,即使使用 ColorAnimation - 你可以简单地不设置 To 属性既没有动画(也没有放置 StopStoryboard 元素),并且可以清楚地看到它们混合在一起。

关于.net - 在 WPF 中定义多个时 DataTrigger 不触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28586884/

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