Search code examples
c#wpfdatatriggercoloranimationwpf-animation

Animate TextBox background when value has changed


I want to animate the textbox (Price) backround color depending on the new value from the ViewModel.

Color can be different depending on the new value (greater 0 -> green - less 0 -> red)

The only animation i can see is at startup when the new value is set. After that the animation will never appear again.

<TextBox HorizontalAlignment="Left" Height="23" Margin="10,178,0,0" TextWrapping="Wrap" Text="{Binding price}" VerticalAlignment="Top" Width="120" x:Name="ChangeField">
    <TextBox.Style>
            <Style>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding price, Converter={StaticResource formatter}}" Value="positive">
                        <DataTrigger.EnterActions>
                            <StopStoryboard BeginStoryboardName="pos"></StopStoryboard>
                            <BeginStoryboard x:Name="pos">
                                <Storyboard>
                                    <ColorAnimation  AutoReverse="True" To="Green" Duration="0:0:0:0.100" Storyboard.TargetProperty="(TextBox.Background).(SolidColorBrush.Color)"></ColorAnimation>
                                </Storyboard>
                            </BeginStoryboard>
                        </DataTrigger.EnterActions>
                        <DataTrigger.ExitActions>
                            <RemoveStoryboard BeginStoryboardName="pos"></RemoveStoryboard>
                        </DataTrigger.ExitActions>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBox.Style>
    </TextBox>

It is possible that the price changes a few times per second, so i need to abort the running animation when a new price value is set.


Solution

  • A storyboard seems kind of overkill for a simple color change. I would bind the background color and create an IValueConverter for the price which is simply following along with the NotificationChanges for Price.

    I'd recommend is using a IValueConverter to bind to the Background element of the Price and isolate the coloring logic there...

    Xaml

    <TextBlock x:Name="ChangeField" 
               Text="{Binding price}" 
               Background="{Binding price, Converter={StaticResource PriceToColorConverter}}" />
    

    Code

    [ValueConversion(typeof(decimal), typeof(Brush))]
    public class PriceToColorConverter : IValueConverer
    {
       public object Convert(object value, Type target)
       {
          decimal price;
          decimal.Parse(value.ToString(), price);
          return (price > 0 ? Brushes.Green : Brushes.Red);
       }
    }