2011-02-09 18 views
5

Mam dość prosty wpftoolkit: datagrid, aby pokazać ofertę na rynku akcji i zapytać.Jak animować tło bloku tekstu podczas zmiany wartości powiązanej właściwości?

Moja siatka jest powiązana z ObservableCollection<PriceViewModel>. Mój PriceViewModel implementuje INotifyPropertyChanged.

Siatka jest poprawnie aktualizowana i udało mi się uzyskać kolor tła do animacji, ale jest ona przerywana w stosowaniu animacji.

Poniżej znajduje się XAML i fragment klasy modelu widoku.

Chodzi o to, aby zabarwić się na czerwono, gdy aktualizacja ceny jest niższa niż poprzednia i zielona, ​​gdy jest wyższa ... nic nadzwyczajnego.

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

A model widok:

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

} 

Odpowiedz

9

Próbowałem tego i wydaje się działać lepiej, jeśli przed rozpoczęciem nowego Państwo zatrzymać Storyboard s. Aby zatrzymać Storyboard, nazwij go i nazywają

<StopStoryboard BeginStoryboardName="bidUpStoryboard"/> 

Spróbuj jak to

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

Ponadto, jeśli BidUp jest ustawiona na true dwa razy z rzędu, to nie spowoduje po raz drugi od przejdzie z true do true, więc jeśli chcesz, aby efekt flashowania pojawiał się za każdym razem, gdy zmieni się wartość, będziesz musiał ustawić go na false w pewnym momencie. na przykład

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

Pracował wielki. Podsumowując, moje podejście wydaje się nieco skomplikowane, czy istnieje lepszy wzór dla tego rodzaju zachowania, czy sposób, w jaki mogę generalizować moje wyzwalacze? – MattC

+0

Czy możemy wykonać tę metodę bez korzystania z DataGrid? – Alkimake

0

Alternatywą może mieć kilka właściwości na PriceViewModel - po jednym dla każdej oferty i askbackgrounds. Możesz wtedy mieć kolekcję, która śledzi, które elementy w ObserveableCollection zostały zaktualizowane. Zegar okresowo sprawdzałby tę kolekcję i resetował kolory tylnych komórek, które miały zostać zresetowane.

Przykładem tutaj:

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

Powiązane problemy