Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to datatrigger an animation upon updated ViewModel property?

I have the following DataGrid cell, which I would like to animate its background colour briefly as soon as the underlying LastTradePrice property changes its value.

<DataGridTextColumn Header="Last Trade Price" Binding="{Binding LastTradePrice}">
     <DataGridTextColumn.CellStyle>
          <Style TargetType="DataGridCell">
             <Style.Triggers>
                // ???
                <DataTrigger Binding="{Binding LastTradePrice}" Value="True"> 
                     <DataTrigger.EnterActions>
                          <BeginStoryboard>
                              <Storyboard>
                                 <ColorAnimation To="Aqua" Duration="0:0:0.3" Storyboard.TargetProperty="Background.(SolidColorBrush.Color)"/>
                              </Storyboard>
                          </BeginStoryboard>
                      </DataTrigger.EnterActions>
                 </DataTrigger>
             </Style.Triggers>
          </Style>
    </DataGridTextColumn.CellStyle>
</DataGridTextColumn>

1) The line <DataTrigger Binding="{Binding LastTradePrice}" Value="True"> makes no sense though.

The property LastTradePrice is obviously not a boolean to be measured with value = True. How can I make the trigger to fire whenever the property is updated? Obviously I have INotification implemented:

        public double LastTradePrice
        {
            get { return _model.LastTradePrice; }
            set
            {
                if (value != _model.LastTradePrice)
                {
                    LastTradePrice = value;
                    OnPropertyChanged("LastTradePrice");
                }
            }
        }

2) If I would have stored the whole style definition inside <Window.Resources>, how would I have accessed the ViewModels property LastTradePrice?

Many Thanks

like image 341
Houman Avatar asked Feb 23 '14 16:02

Houman


1 Answers

As mentioned in the comment you can utilize Binding.TargetUpdated event.

Occurs when a value is transferred from the binding source to the binding target, but only for bindings with the NotifyOnTargetUpdated value set to true.

Which means that if value is pulled from view model into view, and NotifyOnTargetUpdated == True against binding, TargetUpdated event is raised. So it will be raised when value is initially displayed or later when you raise INotifyPropertyChanged.PropertyChanged event in your view model.

<DataGridTextColumn Header="Last Trade Price" Binding="{Binding Path=LastTradePrice, NotifyOnTargetUpdated=True}">
   <DataGridTextColumn.CellStyle>
      <Style TargetType="DataGridCell">
         <Style.Triggers>
            <EventTrigger RoutedEvent="Binding.TargetUpdated">
               <BeginStoryboard>
                  <Storyboard>
                     <ColorAnimation To="Aqua" Duration="0:0:0.3" AutoReverse="True" Storyboard.TargetProperty="Background.(SolidColorBrush.Color)" />
                  </Storyboard>
               </BeginStoryboard>
            </EventTrigger>
         </Style.Triggers>
      </Style>
   </DataGridTextColumn.CellStyle>
</DataGridTextColumn>

Also if want to briefly notify with colour change you want to set AutoReverse="True" against ColorAnimation otherwise Aqua colour will stay. The only downside of this solution is that it will trigger also when DataGrid is created and initial values are loaded.

There is also Binding.SourceUpdated event which works with NotifyOnSourceUpdated against binding and works in the opposite direction to TargetUpdated event. It will be triggered when new value is transmitted from view to view model.

Gets or sets a value that indicates whether to raise the SourceUpdated event when a value is transferred from the binding target to the binding source.

By default both NotifyOnTargetUpdated abd NotifyOnSourceUpdated will be set to false to save on raising 2 additional event when values are transmitted between view and view model.

like image 79
dkozl Avatar answered Sep 19 '22 17:09

dkozl