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

时间:2012-10-01 22:19:39

标签: wpf animation mvvm styles datatrigger

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

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

  • 大多数情况下,标签会将其颜色设置为少量几次,然后停止并且不会再次更改
  • 有时标签只会移动到红色或绿色,并且无论输入值如何都会卡在上面
  • 如果出价下降,差价会增加,但所有3个标签都会动画为相同颜色(如果动画有效)

任何人都可以看到这个问题,并评论一个更好的方法来构建这个吗?我想知道是否有更好的方法来确定价值是上升还是下降而不需要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>

视图模型

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");
        }
    }
}

1 个答案:

答案 0 :(得分:2)

您可以尝试通过DataTrigger.ExitActions停止故事板(您必须将现有的名称命名为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>