none
Perform color animation based on previous and current value of a TextBlock RRS feed

  • Question

  • Hi,

    I have to change the color of a TextBlock to indicate whether the number is positive or negative - red for negative, blue for positive. I have done this by using a DataTrigger and a Converter which returns True/False whether the number is negative/positive. Next requirement is a bit trickier: when the number changes, perform a slow fade to indicate whether the number has increased or decreased from the previous value, and then it fades to whichever color indicates its current position as above.

    What's the easiest way to accomplish this?

    Thanks.

    P.S: I have tried to come up with a DataTrigger using a MultiBinding, so the converter would receive as a parameter the previous value (binded off my view-model). But the behaviour is quite odd.
    Besides, if I forget about the animation and just have a style to show the negative numbers in red and positive in blue through a converter, when I start up the application the value is in black color, and it remains in black until the number is changed by another with the opposite sign. I.e : initial number is 13. If subsequent numbers are 3,12,5 they all are black until a negative number shows up and then it turns into red.

    This my DataTrigger XAML code:


    <Style TargetType="{x:Type TextBlock}" x:Key="PositiveNegativeColorStyle">
      <Style.Triggers>
        <DataTrigger Value="True">
          <DataTrigger.Binding>
            <MultiBinding Converter="{StaticResource NumberIsLessThanParameter}">
              <Binding RelativeSource="{RelativeSource Self}" Path="Text"/>
              <Binding Path="OldValue" Mode="OneWay"/>
            </MultiBinding>
          </DataTrigger.Binding>
          
          <DataTrigger.EnterActions>
            <BeginStoryboard Name="ToRedAnim">
              <Storyboard TargetProperty="Foreground.Color">
                <ColorAnimation From="Transparent" To="Red" Duration="0:0:2" AutoReverse="False" />
              </Storyboard>
            </BeginStoryboard>
          </DataTrigger.EnterActions>
          
          <DataTrigger.ExitActions>
            <!--<StopStoryboard BeginStoryboardName="ToRedAnim"/>-->
          </DataTrigger.ExitActions>
          <!--<Setter Property="Foreground" Value="Red"/>-->
        </DataTrigger>
    
        <DataTrigger Value="False">
          <DataTrigger.Binding>
            <MultiBinding Converter="{StaticResource NumberIsLessThanParameter}">
              <Binding RelativeSource="{RelativeSource Self}" Path="Text"/>
              <Binding Path="OldValue" Mode="OneWay"/>
            </MultiBinding>
          </DataTrigger.Binding>
          
          <DataTrigger.EnterActions>
            <BeginStoryboard Name="ToBlueAnim">
              <Storyboard TargetProperty="Foreground.Color">
                <ColorAnimation From="Transparent" To="Blue" Duration="0:0:2" AutoReverse="False"/>
              </Storyboard>
            </BeginStoryboard>
          </DataTrigger.EnterActions>
          
          <DataTrigger.ExitActions>
            <!--<StopStoryboard BeginStoryboardName="ToBlueAnim"/>-->
          </DataTrigger.ExitActions>
          <!--<Setter Property="Foreground" Value="Blue"/>-->
        </DataTrigger>
      </Style.Triggers>
    </Style>
    Thursday, February 25, 2010 4:55 PM

Answers

  • Hi,

    It sounds like you encountered two issues:  (1) odd behavior when trying to use Animation, and (2) black foreground when first changing the TextBlock content.

    I was able to repro #2 using the MultiBinding approach in your sample.  I don’t know why the animation fails though. I then tried a different approach:  using Binding instead, thereby leaving out the binding to “OldValue”.  When I tried the markup shown below, it seemed to do what you want… the first change in content is displays the foreground in the correct color.  Will this approach work for you?

      <Page.Resources>    
        <local:NumberIsLessThanConverter x:Key="NumberIsLessThanParameter" />
    
        <Style TargetType="{x:Type TextBlock}" x:Key="PositiveNegativeColorStyle">
          <Style.Triggers>
    
              <DataTrigger Value="True" Binding="{Binding ElementName=TargetElement, Path=Text, Converter={StaticResource NumberIsLessThanParameter}}">
    
              <DataTrigger.EnterActions>
                <BeginStoryboard Name="ToRedAnim">
                  <Storyboard TargetProperty="Foreground.Color">
                    <ColorAnimation From="Transparent" To="Red" Duration="0:0:2" />
                  </Storyboard>
                </BeginStoryboard>
              </DataTrigger.EnterActions>
    
              <DataTrigger.ExitActions>
                 <StopStoryboard BeginStoryboardName="ToRedAnim"/>
              </DataTrigger.ExitActions>
    
            </DataTrigger>
    
            <DataTrigger Value="False" Binding="{Binding ElementName=TargetElement, Path=Text, Converter={StaticResource NumberIsLessThanParameter}}">
    
              <DataTrigger.EnterActions>
                <BeginStoryboard Name="ToBlueAnim">
                  <Storyboard TargetProperty="Foreground.Color">
                    <ColorAnimation From="Transparent" To="Blue" Duration="0:0:2" />
                  </Storyboard>
                </BeginStoryboard>
              </DataTrigger.EnterActions>
    
              <DataTrigger.ExitActions>
                 <StopStoryboard BeginStoryboardName="ToBlueAnim"/>
              </DataTrigger.ExitActions>
            </DataTrigger>
          </Style.Triggers>
        </Style>
      </Page.Resources>
    
        <StackPanel>
            <TextBlock Name="TargetElement" Style="{StaticResource PositiveNegativeColorStyle}" FontSize="36" Height="100" Width="100" Background="LightYellow" />
            <Button Click="OnClickPos" Height="60" Width="120" Content="Set Positive" />
            <Button Click="OnClickNeg1" Height="60" Width="120" Content="Set Negative 1" />
            <Button Click="OnClickNeg2" Height="60" Width="120" Content="Set Negative 2" />
        </StackPanel>
    

    Saturday, February 27, 2010 12:12 AM