Working with ObjectAnimationUsingKeyFrames:

ObjectAnimationUsingKeyFrame:

Recently I had requirement to change brush resources on a event like mouse hover, to do this I start over using <ColorAnimation/> but in this we can change color values but not color resources.

To change the brush resource we had to dive into the XAML as Blend doesn’t seem to know about the ObjectAnimationUsingKeyFrames animation type.The ObjectAnimationUsingKeyFrames animation allows you to use object instead of primitive values for your animation keyframes. The only type of keyframe allowed in the ObjectAnimationUsingKeyFrames animation are Discrete keyframes. The reason is that there is no good way to interpolate between object values, I wanted to change the Fill of a rectangle from one resource-based Brush to another. For example, here are the brushes defined in the Resources section:

<LinearGradientBrush x:Key=”MouseHoverBackgroundBrush” EndPoint=”0.5,1″ StartPoint=”0.5,0″>

<GradientStop Color=”#FFEFF1F3″ Offset=”0″/>

<GradientStop Color=”#FFFBFBFB” Offset=”0.018″/>

<GradientStop Color=”#FFEDEDEA” Offset=”0.23″/>

<GradientStop Color=”#FFE0E0E0″ Offset=”0.965″/>

<GradientStop Color=”#FFF7F7F7″ Offset=”1″/>

</LinearGradientBrush>

<SolidColorBrush x:Key=”BackgroundBrush” Color=”#FF122F1A”/>

Now let us take a Button control’s style to work with this.

In button style at design time I have used background property to a brush resource called “ BackgroundBrush” and we wanted to set the MouseHoverBackgroundBrush during the Visual State Manager’s MouseOver state. Since Blend wouldn’t let us do it, we had to write the ObjectAnimationUsingKeyFrames XAML ourselves.

To do this, we created a Storyboard and an ObjectAnimationUsingKeyFrames element inside the MouseOver state (of the Visual State Manager for our Button’s ControlTemplate).In the new element we specified the Storyboard.TargetName and Storyboard.TargetProperty to “theBack” and “Fill“. Inside the animation, we created a DiscreteObjectKeyFrame for our one value. We just wanted to change it to the since new brush so we only needed one. We set the Keytime to “0:0:0” to specify that this should happen immediately.Lastly, we specified the StaticResource for the mouseOverBackBrush as the Value. Here’s the entire MouseOver state XAML:

<Style x:Key=”ButtonStyle1″ TargetType=”Button”>

<Setter Property=”Background” Value=”Blue”/>

<Setter Property=”Template”>

<Setter.Value>

<ControlTemplate TargetType=”Button”>

<Grid>

<VisualStateManager.VisualStateGroups>

<VisualStateGroup x:Name=”CommonStates”>

<VisualState x:Name=”Disabled”/>

<VisualState x:Name=”Normal”/>

<VisualState x:Name=”MouseOver”>

<Storyboard>

<ObjectAnimationUsingKeyFrames Duration=”0″ Storyboard.TargetProperty=”Fill” Storyboard.TargetName=”rt” d:IsOptimized=”True”>

<DiscreteObjectKeyFrame KeyTime=”0:0:0″ Value=”{StaticResource Background}” />

</ObjectAnimationUsingKeyFrames>

</Storyboard>

</VisualState>

<VisualState x:Name=”Pressed”/>

</VisualStateGroup>

</VisualStateManager.VisualStateGroups>

<Rectangle x:Name=”rt” Fill=”{TemplateBinding Background}” StrokeEndLineCap=”Round” StrokeThickness=”2″/>

<Rectangle x:Name=”Hover” Fill=”#FF122F1A” StrokeEndLineCap=”Round” StrokeThickness=”2″ Visibility=”Collapsed”/>

<Border BorderBrush=”Black” BorderThickness=”1″ Background=”{TemplateBinding Background}” Visibility=”Collapsed”/>

<ContentPresenter HorizontalAlignment=”{TemplateBinding HorizontalContentAlignment}” VerticalAlignment=”{TemplateBinding VerticalContentAlignment}”/>

</Grid>

</ControlTemplate>

</Setter.Value>

</Setter>

</Style>

We didn’t need to specify another animation in the Normal state the Visual State Manager automatically handles the resetting of our value back to the original state. It just works. Here’s two pictures of the button before and after the mouse over: