wpf - 如何在标签值更改时设置背景颜色动画

标签 wpf animation mvvm styles datatrigger

我正在尝试获取一个标签,以便在其绑定(bind)的值发生变化时更改背景颜色。如果上升,则暂时呈绿色闪烁。如果下降,则暂时呈红色闪烁。

当我启动应用程序时,我遇到了以下问题:

  • 大多数时候,标签会将其颜色设置为动画几次,然后就停止,不再更改
  • 有时,无论输入值如何,标签都会移至红色或绿色并停留在该位置
  • 如果出价下降,差价将会增加,但所有 3 个标签都将动画为相同颜色(如果动画有效)

任何人都可以看到这有什么问题,并评论更好的结构方式吗?我想知道是否有更好的方法来确定值(value)是上涨还是下跌,而不需要 ViewModel 上的 6 个属性来进行出价、要价和点差?我还想知道是否会频繁更改值(例如每秒 5 次以上)?

谢谢。


查看

<Window x:Class="TestApp.UI.View.QuoteView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="QuoteView" Height="300" Width="300">
    <Window.Resources>
        <Style x:Key="BidStyle">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=BidHigher}" Value="True">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetProperty="Background.Color" To="Green" Duration="0:0:0.2" AutoReverse="True"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                </DataTrigger>
                <DataTrigger Binding="{Binding Path=BidLower}" Value="True">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetProperty="Background.Color" To="Red" Duration="0:0:0.2" AutoReverse="True"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                </DataTrigger>
                <DataTrigger Binding="{Binding Path=AskHigher}" Value="True">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetProperty="Background.Color" To="Green" Duration="0:0:0.2" AutoReverse="True"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                </DataTrigger>
                <DataTrigger Binding="{Binding Path=AskLower}" Value="True">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetProperty="Background.Color" To="Red" Duration="0:0:0.2" AutoReverse="True"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                </DataTrigger>
                <DataTrigger Binding="{Binding Path=SpreadHigher}" Value="True">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetProperty="Background.Color" To="Green" Duration="0:0:0.2" AutoReverse="True"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                </DataTrigger>
                <DataTrigger Binding="{Binding Path=SpreadLower}" Value="True">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetProperty="Background.Color" To="Red" Duration="0:0:0.2" AutoReverse="True"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid>
        <Label Content="Bid" HorizontalAlignment="Left" Margin="21,10,0,0" VerticalAlignment="Top" />
        <Label Content="Ask" HorizontalAlignment="Left" Margin="19,53,0,0" VerticalAlignment="Top"/>
        <Label Content="Spread" HorizontalAlignment="Left" Margin="19,99,0,0" VerticalAlignment="Top"/>
        <Label x:Name="BidLabel" HorizontalAlignment="Left" Margin="102,10,0,0" VerticalAlignment="Top" Content="{Binding Path=Quote.Bid}" Style="{StaticResource ResourceKey=BidStyle}"/>
        <Label x:Name="AskLabel" HorizontalAlignment="Left" Margin="102,53,0,0" VerticalAlignment="Top" Content="{Binding Path=Quote.Ask}" Style="{StaticResource ResourceKey=BidStyle}"/>
        <Label x:Name="SpreadLabel" HorizontalAlignment="Left" Margin="102,99,0,0" VerticalAlignment="Top" Content="{Binding Path=Quote.BidAskSpread}" Style="{StaticResource ResourceKey=BidStyle}"/>
    </Grid>
</Window>

View 模型

public class QuoteViewModel : ViewModelBase
{
    private readonly FakeDataGenerator _dataGenerator;
    private Quote _quote;
    private bool _bidHigher;
    private bool _bidLower;
    private bool _askHigher;
    private bool _askLower;
    private bool _spreadHigher;
    private bool _spreadLower;

    public QuoteViewModel()
    {
        _dataGenerator = new FakeDataGenerator();
        _dataGenerator.NewQuoteEvent += DataGeneratorOnNewQuoteEvent;
    }

    private void DataGeneratorOnNewQuoteEvent(Quote quote)
    {
        Quote = quote;
    }

    public Quote Quote
    {
        get { return _quote; }
        set 
        {
            if (_quote != value)
            {
                UpdateQuoteComparisons(_quote, value);
                _quote = value;
                OnPropertyChanged("Quote");
            }
        }
    }

    private void UpdateQuoteComparisons(Quote existingQuote, Quote newQuote)
    {
        if(existingQuote == null)
        {
            return;
        }

        if (newQuote.Bid > existingQuote.Bid)
        {
            BidHigher = true;
        }
        else if (newQuote.Bid < existingQuote.Bid)
        {
            BidLower = true;
        }

        if (newQuote.Ask > existingQuote.Ask)
        {
            AskHigher = true;
        }
        else if (newQuote.Ask < existingQuote.Ask)
        {
            AskLower = true;
        }

        if (newQuote.BidAskSpread > existingQuote.BidAskSpread)
        {
            SpreadHigher = true;
        }
        else if (newQuote.BidAskSpread < existingQuote.BidAskSpread)
        {
            SpreadLower = true;
        }
    }

    public bool BidHigher
    {
        get { return _bidHigher; }
        set
        {
            _bidHigher = value;
            OnPropertyChanged("BidHigher");
        }
    }

    public bool BidLower
    {
        get { return _bidLower; }
        set
        {
            _bidLower = value;
            OnPropertyChanged("BidLower");
        }
    }

    public bool AskHigher
    {
        get { return _askHigher; }
        set
        {
            _askHigher = value;
            OnPropertyChanged("AskHigher");
        }
    }

    public bool AskLower
    {
        get { return _askLower; }
        set
        {
            _askLower = value;
            OnPropertyChanged("AskLower");
        }
    }

    public bool SpreadHigher
    {
        get { return _spreadHigher; }
        set
        {
            _spreadHigher = value;
            OnPropertyChanged("SpreadHigher");
        }
    }

    public bool SpreadLower
    {
        get { return _spreadLower; }
        set
        {
            _spreadLower = value;
            OnPropertyChanged("SpreadLower");
        }
    }
}

最佳答案

您可以尝试通过 DataTrigger.ExitActions 停止 Storyboard(您必须命名现有的 BeginStoryboard):

        <DataTrigger Binding="{Binding Path=SpreadLower}" Value="True">
            <DataTrigger.EnterActions>
                <BeginStoryboard Name="SpreadLowerStoryboard>
                    <Storyboard>
                        <ColorAnimation Storyboard.TargetProperty="Background.Color" To="Red" Duration="0:0:0.2" AutoReverse="True"/>
                    </Storyboard>
                </BeginStoryboard>
            </DataTrigger.EnterActions>
            <DataTrigger.ExitActions>
                <StopStoryboard BeginStoryboardName="SpreadLowerStoryboard" />
            </DataTrigger.ExitActions>
        </DataTrigger>

关于wpf - 如何在标签值更改时设置背景颜色动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12681931/

相关文章:

wpf - 在 MultiBinding 中管理绑定(bind)的 targetType

c# - WPF Prism - 在导航中发送对象

java - 如何使java形状以圆形动画?

jquery - 复制 CSS "background-image"的效果 - 替代方法?

.net - 当我们过渡到 WPF 和 MVVM 时,哪种 .NET 2.0 开发模式(MVP、MVC 等)最适合允许轻松重用?

c# - 在 C# (WPF) 中,当 UI 线程中的数据立即更改时,是否会发生数据绑定(bind)?

javascript - Vue.js 怎么能像 Angular.js 那样配置 templateUrl 呢?

wpf - 与 PRISM 的对话交互请求

c# - WPF 如何将 FlowDocument BGImage 转换为 FixedDocument 并在 DocumentViewer 中显示?

jquery函数需要先取消其他函数