Search code examples
wpfanimationwpf-controlsstoryboarduielement

WPF: What's the right way to make a UIElement visible right at the moment when a storyboard begins


I'm trying out a simple animation of pictures sliding in on top of each other, the problem is, I don't know when to set the visibility of the new picture that slides in. I don't wanna show the picture on top until the animation starts. The sequence is like this, one stretched picture on the screen, then another picture of the same dimensions slides in on top of the previous picture. The new picture will have a higher Z-index compared to the old picture. I've set up a storyboard, and visibility of the new picture to hidden. So when do I make the new picture visible? Is it right before calling StoryBoard.Begin(MyNewPicture)? So it becomes

    //create picture object 
    //...
    MyNewPicture.Visibility = Visiblity.Hidden;
    //do some intialisation, and create StoryBoard
    //...
    MyNewPicture.Visibility = Visibility.Visible;
    MyStoryBoard.Begin(MyNewPicture);`

This works on my fast computer, but I wonder, if I run it on a slow computer, and if there is some kind of performance slow down / screen lag etc, will it make the new picture appear to cover the picture below it when it becomes visible, just before the animation starts? This will create a flicker on the screen which is not desirable.

Or should I put the visibility as part of the animation? Please take a look at this answer to a previous slightly similar question by someone else. Should I use ObjectAnimationUsingKeyFrames in the Xaml instead? Please note that once the animation starts, the new picture should be visible (forever), there's no need to toggle visibility in my case. I just want the New Picture to be visible right when the animation starts and not before the animation(or else it will block the previous picture).


Solution

  • If you want to change the Visibility by Animation, you have to use ObjectAnimationUsingKeyFrames:

        <Storyboard x:Key="StartPicture">
            <ObjectAnimationUsingKeyFrames Duration="0:0:0.1" Storyboard.TargetProperty="Visibility">
                <ObjectKeyFrameCollection>
                    <DiscreteObjectKeyFrame Value="{x:Static Visibility.Visible}" KeyTime="0:0:0"></DiscreteObjectKeyFrame>
                </ObjectKeyFrameCollection>
            </ObjectAnimationUsingKeyFrames>
            <DoubleAnimation BeginTime="00:00:00.1" Storyboard.TargetProperty="Property" To="Value" />
        </Storyboard>
    

    You could also animate the Opacity from 0 to 100 to make the picture visible:

        <Storyboard 
            <DoubleAnimation Storyboard.TargetProperty="Opacity" To="100" Duration="0:0:0.1"  />
            <DoubleAnimation BeginTime="0:0:0.1" Storyboard.TargetProperty="PropertyToAnimate" To="Value"  />
        </Storyboard>
    

    This way you first animate the Opacity-property to 100 (in 100ms) and after this (with BeginTime="0:0:0.1") comes the rest.