Как анимировать фон текстового блока при изменении значения связанного свойства? - PullRequest
5 голосов
/ 09 февраля 2011

У меня есть довольно простой 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 ]

9 голосов
/ 09 февраля 2011

Я попробовал это, и, похоже, будет лучше, если вы остановите Storyboard s перед тем, как запустить новый.Чтобы остановить 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 два раза подряд, ононе будет срабатывать во второй раз, так как будет переходить от истинного к истинному, поэтому, если вы хотите, чтобы мигающий эффект появлялся каждый раз, когда значение изменяется, вам придется установить его на ложное значение в какой-то момент.например,

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"); }
}
0 голосов
/ 03 мая 2012

Альтернативой может быть пара свойств на PriceViewModel - по одному для каждой из ставок и заданий.После этого вы можете получить коллекцию, которая будет отслеживать, какие элементы в ObserveableCollection были обновлены.Таймер будет периодически проверять эту коллекцию и сбрасывать цвета ячеек, которые должны были быть сброшены.

Пример здесь:

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

...