如何在更改绑定属性的值时为文本块的背景设置动画?

时间:2011-02-09 15:29:00

标签: wpf animation wpftoolkit

我有一个非常简单的wpftoolkit:datagrid来显示股票市场出价并询问。

我的网格绑定到ObservableCollection<PriceViewModel>。我的PriceViewModel实施INotifyPropertyChanged

网格正确更新,我设法将背景颜色设置为动画,但在应用动画时间歇性。

以下是视图模型类的XAML和片段。

这个想法只是在价格更新低于之前的时候变成红色,而当它更高时是绿色......没什么太花哨的。

     <WpfToolkit:DataGrid Name="PriceDataGrid" RowHeaderWidth="5" 
AutoGenerateColumns="False" VerticalContentAlignment="Center" Margin="0,33,0,0" HorizontalAlignment="Left" Width="868">
        <WpfToolkit:DataGrid.Columns>
            <WpfToolkit:DataGridTemplateColumn Header="Bid"  MinWidth="40">
                <WpfToolkit:DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Bid}" Margin="3,1" x:Name="txtTextBlock">
                            <TextBlock.Background>
                                <SolidColorBrush Color="Transparent"></SolidColorBrush>
                            </TextBlock.Background>
                        </TextBlock>
                        <DataTemplate.Triggers>
                            <DataTrigger Binding="{Binding BidUp}" Value="True">
                                <DataTrigger.EnterActions>
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <ColorAnimation 
                                                BeginTime="00:00:00"
                                                Duration="0:0:0.1" 
                                                To="Green" 
                                                AutoReverse="True"
                                                Storyboard.TargetName="txtTextBlock" 
                                                Storyboard.TargetProperty="(TextBlock.Background).(SolidColorBrush.Color)">
                                            </ColorAnimation>
                                        </Storyboard>
                                    </BeginStoryboard>
                                </DataTrigger.EnterActions>
                            </DataTrigger>
                            <DataTrigger Binding="{Binding BidDown}" Value="True">
                                <DataTrigger.EnterActions>
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <ColorAnimation 
                                                BeginTime="00:00:00"
                                                Duration="0:0:0.1" 
                                                To="Red" 
                                                AutoReverse="True"
                                                Storyboard.TargetName="txtTextBlock" 
                                                Storyboard.TargetProperty="(TextBlock.Background).(SolidColorBrush.Color)">
                                            </ColorAnimation>
                                        </Storyboard>
                                    </BeginStoryboard>
                                </DataTrigger.EnterActions>
                            </DataTrigger>
                        </DataTemplate.Triggers>
                    </DataTemplate>
                </WpfToolkit:DataGridTemplateColumn.CellTemplate>
            </WpfToolkit:DataGridTemplateColumn>
            <WpfToolkit:DataGridTextColumn Header="Ask" Binding="{Binding Path=Ask}" MinWidth="40" />
        </WpfToolkit:DataGrid.Columns>
    </WpfToolkit:DataGrid>

视图模型:

public class PriceViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    Price _price;

    private bool _bidUp = false;
    private bool _bidDown = false;


    public bool BidUp
    {
        get
        {
            return _bidUp;
        }

        set
        {
            _bidUp = value;
            OnPropertyChanged("BidUp");
        }
    }
    public bool BidDown
    {
        get
        {
            return _bidDown;
        }

        set
        {
            _bidDown = value;
            OnPropertyChanged("BidDown");
        }
    }

    public double Bid 
    { 
        get { return _price.Bid; }
        set
        {
            BidUp = (value > _price.Bid);
            BidDown = (value < _price.Bid);

            _price.Bid = value; 
            OnPropertyChanged("Bid");
        } 
    }

    public double Ask 
    { 
        get { return _price.Ask; } 
        set 
        {
            AskUp = (value > _price.Ask);
            _price.Ask = value; 
            OnPropertyChanged("Ask"); 
        } 
    }


    public PriceViewModel(Price price)
    {
        _price = price;
    }

    private void OnPropertyChanged(string propertyName)
    {
        if(PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

}

2 个答案:

答案 0 :(得分:9)

我试过这个,如果你在启动新版本之前停止Storyboard,它似乎会更好。要停止Storyboard,请为其命名并致电

<StopStoryboard BeginStoryboardName="bidUpStoryboard"/>

尝试这样

<DataTemplate.Triggers>
    <DataTrigger Binding="{Binding BidUp}" Value="True">
        <DataTrigger.EnterActions>
            <StopStoryboard BeginStoryboardName="bidUpStoryboard"/>
            <StopStoryboard BeginStoryboardName="bidDownStoryboard"/>
            <BeginStoryboard Name="bidUpStoryboard">
                <Storyboard BeginTime="00:00:00">
                    <ColorAnimation 
                        BeginTime="00:00:00"
                        Duration="0:0:0.1" 
                        To="Green" 
                        AutoReverse="True"
                        Storyboard.TargetName="txtTextBlock" 
                        Storyboard.TargetProperty="(TextBlock.Background).(SolidColorBrush.Color)">
                    </ColorAnimation>
                </Storyboard>
            </BeginStoryboard>
        </DataTrigger.EnterActions>
    </DataTrigger>
    <DataTrigger Binding="{Binding BidDown}" Value="True">
        <DataTrigger.EnterActions>
            <StopStoryboard BeginStoryboardName="bidUpStoryboard"/>
            <StopStoryboard BeginStoryboardName="bidDownStoryboard"/>
            <BeginStoryboard Name="bidDownStoryboard">
                <Storyboard BeginTime="00:00:00">
                    <ColorAnimation 
                        BeginTime="00:00:00"
                        Duration="0:0:0.1" 
                        To="Red" 
                        AutoReverse="True"
                        Storyboard.TargetName="txtTextBlock" 
                        Storyboard.TargetProperty="(TextBlock.Background).(SolidColorBrush.Color)">
                    </ColorAnimation>
                </Storyboard>
            </BeginStoryboard>
        </DataTrigger.EnterActions>
    </DataTrigger>
</DataTemplate.Triggers>

此外,如果BidUp连续两次设置为true,则它将不会第二次触发,因为它将从true变为true,因此如果您希望每次出现闪烁效果值变化你必须在某些时候将其设置为false。 e.g。

public double Bid
{
    get { return _price.Bid; }
    set
    {
        BidUp = false;
        BidDown = false;
        BidUp = (value > _price.Bid);
        BidDown = (value < _price.Bid);
        _price.Bid = value;
        OnPropertyChanged("Bid"); }
}

答案 1 :(得分:0)

另一种选择可能是在您的PriceViewModel上拥有一些属性 - 每个属性都有一个属于bid和askbackgrounds。然后,您可以拥有一个集合,可以跟踪ObserveableCollection中的哪些项目已更新。计时器会定期检查此集合,并重置要重置的单元格颜色。

这里有一个例子:

http://noelwatson.com/blog/2012/05/01/WPFBlotterflashingCellsWhenUpdated.aspx