2011-02-09 1 views
5

Ho un wpftoolkit piuttosto semplice: datagrid per mostrare l'offerta e chiedere.Come animare lo sfondo di un blocco di testo quando si modifica il valore della proprietà associata?

La mia rete è vincolata a ObservableCollection<PriceViewModel>. I miei strumenti PriceViewModelINotifyPropertyChanged.

La griglia si aggiorna correttamente e sono riuscito ad ottenere il colore di sfondo da animare ma è intermittente nell'applicare l'animazione.

Segue lo XAML e lo snippet della classe del modello di visualizzazione.

L'idea è solo quella di colorare il rosso quando un aggiornamento del prezzo è inferiore al precedente e verde quando è più alto ... niente di troppo.

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

E il modello di vista:

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

} 

risposta

9

Ho provato questo e sembra funzionare meglio se ci si ferma i Storyboard s prima di iniziare quello nuovo. Per arrestare un Storyboard, un nome e lo chiamano

<StopStoryboard BeginStoryboardName="bidUpStoryboard"/> 

Prova in questo modo

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

Inoltre, se BidUp è impostata su true due volte di fila, non si innescherà la seconda volta dal passerà da vero a vero, quindi se vuoi che l'effetto lampeggiante appaia ogni volta che un valore cambia, dovrai impostarlo su falso ad un certo punto. per esempio.

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

funzionava. Nel complesso, il mio approccio si sente un po 'contorto, esiste un modello migliore per questo tipo di comportamento o un modo in cui posso generalizzare i miei trigger? – MattC

+0

Possiamo fare questo metodo senza usare DataGrid? – Alkimake

0

Un'alternativa può essere quella di avere un paio di proprietà sul PriceViewModel - uno per ogni dell'offerta e askbackgrounds. È quindi possibile disporre di una raccolta che tenga traccia di quali elementi nel numero ObserveableCollection sono stati aggiornati. Un timer controlla periodicamente questa raccolta e ripristina i colori di retro della cella che dovevano essere ripristinati.

Un esempio qui:

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