How to animate the background of a textblock when changing the value of the bound property?

那年仲夏 提交于 2019-12-21 16:58:43

问题


I have a pretty simple wpftoolkit:datagrid to show stock market bid and ask.

My grid is bound to an ObservableCollection<PriceViewModel>. My PriceViewModel implements INotifyPropertyChanged.

The grid correctly updates and I have managed to get the background color to animate but it is intermittent in apply the animation.

Below is the XAML and snippet of the view model class.

The idea is just to color red when a price update is lower than the previous and green when it's higher...nothing too fancy.

     <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>

And the view model:

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

}

回答1:


I tried this and it seems to work better if you stop the Storyboards before you start the new one. To stop a Storyboard, name it and call

<StopStoryboard BeginStoryboardName="bidUpStoryboard"/>

Try it like this

<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>

Also, if BidUp is set to true two times in a row, it won't trigger the second time since it will go from true to true, so if you want the flashing effect to appear each time a value changes you will have to set it to false at some point. 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"); }
}



回答2:


An alternative may be to have a couple of properties on your PriceViewModel - one for each of the bid and askbackgrounds. You could then have a collection that kept track of what items in the ObserveableCollection had been updated. A timer would periodically check this collection, and reset the cell back colours that were due to be reset.

An example here:

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



来源:https://stackoverflow.com/questions/4946912/how-to-animate-the-background-of-a-textblock-when-changing-the-value-of-the-boun

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!