Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c#

wpf

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;
}
like image 578
DeadZone Avatar asked Jan 02 '15 14:01

DeadZone


1 Answers

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;
}
like image 200
Clemens Avatar answered Sep 22 '22 04:09

Clemens