WPF - 根据 TextBlock 的先前值和当前值执行颜色动画

发布于 2024-08-22 17:45:49 字数 227 浏览 2 评论 0原文

我必须更改 TextBlock 的颜色来指示数字是正数还是负数 - 红色表示负数,蓝色表示正数。我通过使用 DataTrigger 和 Converter 来完成此操作,无论数字是负数还是正数,它都会返回 True/False。 下一个要求有点棘手:当数字发生变化时,执行缓慢的淡入淡出以指示数字相对于之前的值是增加还是减少,然后淡出到如上所述指示其当前位置的颜色。

实现这一目标的最简单方法是什么?

谢谢。

I have to change the color of a TextBlock to indicate whether the number is positive or negative - red for negative, blue for positive. I have done this by using a DataTrigger and a Converter which returns True/False whether the number is negative/positive.
Next requirement is a bit trickier: when the number changes, perform a slow fade to indicate whether the number has increased or decreased from the previous value, and then it fades to whichever color indicates its current position as above.

What's the easiest way to accomplish this?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

少年亿悲伤 2024-08-29 17:45:49

使用触发器的方法是正确的,要启动动画,您可以使用 触发器.EnterAction

Approach with triggers is correct, and to launch animation you can use Trigger.EnterAction.

葵雨 2024-08-29 17:45:49

我认为 Trigger.EnterAction 的方法不会起作用。
为了应用新的动画,您必须指定 Trigger.ExitAction 来删除当前动画,结果颜色恢复为默认值。当您启动新动画时,它将从默认颜色(现在已成为当前颜色)动画到新颜色。
将动画源值绑定到某个动态值不起作用,因为 auf Freezable。
我通过引入一个附加属性解决了这个问题,该属性从对象当前具有的任何颜色到指定的颜色生成动态动画:

<TextBlock Text="text">
    <local:AnimationHelper.Animation>
        <local:ConstantColorAnimation 
            TargetProperty="Foreground" 
            To="{Binding CurrentState, Converter={StaticResource stateToColor}}" 
            Speed="1.5" /> 
    </local:AnimationHelper.Animation>
</TextBlock Text="text">

每当 CurrentState 属性更改为由状态到颜色转换器。这是来自具有 CurrentState 属性的 ViewModel 的 DataTemplate。如果您希望它直接绑定到文本,您必须编写一个 TextToColorConverter。

下面是 ConstantColorAnimation 的相关代码示例:

private void CreateAnimation()
{
    if (this.ResolvedTargetProperty == null)
    {
        return;
    }
    var from = (Color)this.Context.GetValue(this.ResolvedTargetProperty);
    this.RemoveAnimation(this.ResolvedTargetProperty);
    if (this.Speed == 0)
    {
        this.Context.SetValue(this.ResolvedTargetProperty, from);
        return;
    }
    if (this.Speed < 0)
    {
        this.Context.SetValue(this.ResolvedTargetProperty, this.To);
        return;
    }
    var a = new ColorAnimation(
        from, this.To, new Duration(TimeSpan.FromSeconds(Math.Abs(this.To - from) / this.Speed)));
    this.Context.BeginAnimation(this.ResolvedTargetProperty, a);
}

您还可以使用 Silverlight 中的行为框架,而不是自己滚动这一切。 AFAIK 它与 WPF 完全兼容,您可以直接使用该程序集。您甚至可以 找到一种行为,它已经满足了您的需要。

I don't think the approach with Trigger.EnterAction will work.
In order to apply a new animation you will have to specify Trigger.ExitAction that will remove the current animation and as a result the color reverts to its default. When you then start the new animation it will then animate from its default color (wich now has become the current color) to the new color.
Binding the Animations From value to some dynamic value doesn't work because auf Freezable.
I solved this propblem by introducing an attached property generates the animation on the fly animation from whatever color the object currently has to the spechified one:

<TextBlock Text="text">
    <local:AnimationHelper.Animation>
        <local:ConstantColorAnimation 
            TargetProperty="Foreground" 
            To="{Binding CurrentState, Converter={StaticResource stateToColor}}" 
            Speed="1.5" /> 
    </local:AnimationHelper.Animation>
</TextBlock Text="text">

This will animate the foreground of the TextBlock whenever the CurrentState property changes to the new color that is returned by the StateToColorConverter. This is from DataTemplate for a ViewModel that has a CurrentState property. IF you want it to bind directly to the text you would have to write a TextToColorConverter.

Here is an example of the relevant code for a ConstantColorAnimation:

private void CreateAnimation()
{
    if (this.ResolvedTargetProperty == null)
    {
        return;
    }
    var from = (Color)this.Context.GetValue(this.ResolvedTargetProperty);
    this.RemoveAnimation(this.ResolvedTargetProperty);
    if (this.Speed == 0)
    {
        this.Context.SetValue(this.ResolvedTargetProperty, from);
        return;
    }
    if (this.Speed < 0)
    {
        this.Context.SetValue(this.ResolvedTargetProperty, this.To);
        return;
    }
    var a = new ColorAnimation(
        from, this.To, new Duration(TimeSpan.FromSeconds(Math.Abs(this.To - from) / this.Speed)));
    this.Context.BeginAnimation(this.ResolvedTargetProperty, a);
}

Instead of rolling this all by yourself you could also use the Behavior Framework from Silverlight. AFAIK it is full compatible with WPF and you can use the assembly directly. You might even find a behavior, that already does what you need.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文