views:

220

answers:

1

I have a really basic user control with a button that has an image. I want to animate the image of the button, by changing it to a different image.

<UserControl.Resources>
    <Image x:Key="GlyphDefault" Source="pack://application:,,,/X;component/images/Glyphs_Default.png" Height="8" Width="8" />
    <Image x:Key="GlyphClicked" Source="pack://application:,,,/X;component/images/Glyphs_Click.png" Height="8" Width="8"  />

</UserControl.Resources>
    <Grid>
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup Name="MouseStates">
            <VisualState Name="MouseHover" >
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames
                                Storyboard.TargetName="GlyphButton"
                                Storyboard.TargetProperty="Content"
                                Duration="0:0:1" >
                        <ObjectAnimationUsingKeyFrames.KeyFrames>
                            <DiscreteObjectKeyFrame KeyTime="0:0:1">
                                <DiscreteObjectKeyFrame.Value="{StaticResource GlyphClicked}" />
                            </DiscreteObjectKeyFrame>
                        </ObjectAnimationUsingKeyFrames.KeyFrames>
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
            <VisualState Name="MouseNotHover" >
            </VisualState>
        </VisualStateGroup>

    </VisualStateManager.VisualStateGroups>
    <Button x:Name="GlyphButton" 
            MouseLeave="GlyphButton_MouseLeave"
            MouseEnter="GlyphButton_MouseEnter"
            Content="{StaticResource GlyphDefault}"
            />
</Grid>

Unfortunately, when I run this, and hover over the button I get "Freezable cannot be frozen" exception (the Mouse event handlers change the states). It appears that it's trying to freeze the current image, but can't for some reason.

I've tried doing it without using a static resource (just putting the Image inline) too, but same error. Oddly, I can find very little documentation or blogs about doing animations on the Content property. I'd have to imagine this would be a common scenario. Any ideas as to what I'm doing wrong?

I greatly appreciate your help on this!

+2  A: 

This is probably not the best (or easiest) way to go about this. The Content property is definitely not what the WPF designers had in mind for animations. Here is how I would do this instead:

  1. Set the Button.Content to be a Grid with both of the images placed inside (thus, overlaying each other).
  2. Set the Opacity on the Image you want to be initially visible to 1.0 and 0.0 on the Image to be initially hidden.
  3. Animate the Opacity using a DoubleAnimation rather than an ObjectAnimation- you can switch the images by animating one's opacity down to 0.0 while simultaneously bringing the other one up to 1.0. Furthermore, depending on the duration, this will gave you a nice fading transition.
Charlie
Thanks Charlie. I had considered that, but thought that it felt hackish. One thing that I'm learning with WPF though is some things that feel a little hackish are actually best practices :-)
Kang Su