domenica 24 luglio 2011

How to animate an image in MVVM

I want to design a "tableau de bord" with some indicators blinking or animating as soon as a boolean condition is true.
The indicators are simple images, the blinking is obtained changing the image opacity in a Storyboard.

<Storyboard x:Key="BlinkingAnimation">
  <DoubleAnimation Storyboard.TargetProperty="(Image.Opacity)"    
    BeginTime="0:0:0" Duration="0:0:0.5"    
    From="1.0" To="0.0" RepeatBehavior="Forever" AutoReverse="True"/>
</Storyboard>

The animaton will start on a DataTrigger bound to a Property defined in the ViewModel


First recipe: just edit the style of the Image in the XAML

<Image Source="/MvvmBlinkingImage;component/Images/favorite.png" >
  <Image.Style>
     <Style>
      <Style.Triggers>
        <DataTrigger Binding="{Binding Property1}" Value="true">
          <DataTrigger.EnterActions>
            <BeginStoryboard Storyboard="{StaticResource BlinkingAnimation}" x:Name="blink"/>
          </DataTrigger.EnterActions>
          <DataTrigger.ExitActions>
            <StopStoryboard BeginStoryboardName="blink" />
          </DataTrigger.ExitActions>
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </Image.Style>
 
</Image> 

Second recipe: Create a custom control inherited from Image. The control registers a dependency property to bind to the DataTrigger


public class AnimatedImage : Image
{
        public static DependencyProperty IsBlinkingProperty =
            DependencyProperty.Register("IsBlinking", typeof(bool), typeof(AnimatedImage));
 
        public bool IsBlinking
        {
            get { return (bool)base.GetValue(IsBlinkingProperty); }
            set { base.SetValue(IsBlinkingProperty, value); }
        }
}

Now add a new style to a DictionaryResource for the new AnimatedImage control:


<
Style x:Key="AnimatedImageStyle" TargetType="{x:Type uc:AnimatedImage}">
  <Style.Triggers>
    <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsBlinking}" Value="true">
      <DataTrigger.EnterActions>
        <BeginStoryboard Storyboard="{StaticResource BlinkingAnimation}" x:Name="blink"/>
      </DataTrigger.EnterActions>
      <DataTrigger.ExitActions>
        <StopStoryboard BeginStoryboardName="blink" />
      </DataTrigger.ExitActions>
    </DataTrigger>
  </Style.Triggers>
</Style>   

Please note that IsBlinking is a property of AnimateImage and not of the ViewModel, so it is Necessary override the DefaultContext with RelativeSource Self.Here an useful link on WPF binding: http://www.nbdtech.com/Free/WpfBinding.pdf

Eventually use the AnimateImage control and AnimatedImageStyle in the XAML:

<uc:AnimatedImage IsBlinking="{Binding Property1}" Style="{StaticResource AnimatedImageStyle}" Source="/MvvmBlinkingImage;component/Images/favorite.png" />



Nessun commento:

Posta un commento