WPF Fade Out Animation - Can't Change Opacity Any More

13,174

Solution 1

By default, an animation's FillBehavior is set to HoldEnd, which means that the animation holds the final value of the target property. If you want to reset the value later, you either need to remove the animation, or you set the FillBehavior to Stop. You could then add a handler for the animation's Completed event to keep the final value manually.

Note also that you don't need a timer to delay the start of the animation. You may set its BeginTime property instead.

Finally, no Storyboard is needed to animate a single property. You could call UIElement.BeginAnimation instead.

private void btnChangeLabel_Click(object sender, RoutedEventArgs e)
{
    var animation = new DoubleAnimation
    {
        To = 0,
        BeginTime = TimeSpan.FromSeconds(5),
        Duration = TimeSpan.FromSeconds(2),
        FillBehavior = FillBehavior.Stop
    };

    animation.Completed += (s, a) => lblTest.Opacity = 0;

    lblTest.BeginAnimation(UIElement.OpacityProperty, animation);
}

private void btnResetOpacity_Click(object sender, RoutedEventArgs e)
{
    lblTest.Opacity = 1;
}

Solution 2

Its due to the "fill behavior" of the animation. It's effectively holding on to the value after the animation and not letting go, preventing it from being updated.

Its an easy fix, change the fill behavior to stop and add an event handler to change the opacity value to 0 after the animation (otherwise it will go back to 1)

animation.FillBehavior = FillBehavior.Stop;
animation.Completed += delegate 
{
    lblTest.Opacity = 0;
};

I have tested this with your code and it worked.

Ben

Share:
13,174

Related videos on Youtube

DeadZone
Author by

DeadZone

Updated on September 15, 2022

Comments

  • DeadZone
    DeadZone over 1 year

    I have a WPF window with a label control used for messages to the user. After a few seconds, I want the message to fade away. I have created a DispatcherTimer and a storyboard to do this. (The timer delays for 5 seconds and then the tick event fires and the message fades away.) It successfully fades away, but the next message still has its opacity set to 0. (So the user cannot see it.) Obviously, I tried setting the opacity back to 1, but that fails with no exceptions. (that is, I can step over that line of code with no problems, but the opacity is still 0 after executing it.) Can anyone tell me what I'm doing wrong? Here is some code from a test project with just a label control, a button to set the label's content and the fade animation, and a button to attempt to reset the opacity.

    XAML:

    <Window x:Class="WpfTestApplication2.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="100" Width="525">
        <Grid>
            <StackPanel x:Name="stkHeaderBar" Grid.Row="0" Background="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}" Orientation="Horizontal" FlowDirection="RightToLeft">
                <Label x:Name="lblTest" Content="lblTest"/>
                <Button x:Name="btnChangeLabel" Content="ChangeLabel" Click="btnChangeLabel_Click"/>
                <Button x:Name="btnResetOpacity" Content="Reset Opacity" Click="btnResetOpacity_Click"/>
            </StackPanel>
        </Grid>
    </Window>
    

    C#:

    private void btnChangeLabel_Click(object sender, RoutedEventArgs e)
    {
        lblTest.Content = "Testing1...Testing2...Testing3";
        lblTest.Opacity = 1;
    
        // Create a storyboard to contain the animations.
        Storyboard storyboard = new Storyboard();
        TimeSpan duration = new TimeSpan(0, 0, 2);
    
        // Create a DoubleAnimation to fade the not selected option control
        DoubleAnimation animation = new DoubleAnimation();
    
        animation.From = 1.0;
        animation.To = 0.0;
        animation.Duration = new Duration(duration);
        // Configure the animation to target de property Opacity
        Storyboard.SetTargetName(animation, lblTest.Name);
        Storyboard.SetTargetProperty(animation, new PropertyPath(Control.OpacityProperty));
        // Add the animation to the storyboard
        storyboard.Children.Add(animation);
    
        // Begin the storyboard
        storyboard.Begin(this);
    }
    
    private void btnResetOpacity_Click(object sender, RoutedEventArgs e)
    {
        lblTest.Opacity = 1;
    }