WPF 淡出动画 - 不能再改变不透明度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27744097/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF Fade Out Animation - Can't Change Opacity Any More
提问by DeadZone
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 DispatcherTimerand 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.
我有一个带有标签控件的 WPF 窗口,用于发送给用户的消息。几秒钟后,我希望消息消失。我已经创建了DispatcherTimer一个故事板来做到这一点。(计时器延迟 5 秒,然后滴答事件触发并且消息消失。)它成功消失了,但下一条消息的不透明度仍然设置为 0。(因此用户看不到它。)显然,我试过了将不透明度设置回 1,但无一例外地失败。(也就是说,我可以毫无问题地跳过那行代码,但执行后不透明度仍然为 0。)谁能告诉我我做错了什么?这是来自测试项目的一些代码,只有一个标签控件、一个用于设置标签内容和淡入淡出动画的按钮,以及一个尝试重置不透明度的按钮。
XAML:
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#:
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;
}
回答by Clemens
By default, an animation's FillBehavioris 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 Completedevent to keep the final value manually.
默认情况下,动画的FillBehavior设置为HoldEnd,这意味着动画保存目标属性的最终值。如果以后要重置该值,则需要删除动画,或者将 FillBehavior 设置为Stop。然后,您可以为动画Completed事件添加处理程序以手动保留最终值。
Note also that you don't need a timer to delay the start of the animation. You may set its BeginTimeproperty instead.
另请注意,您不需要计时器来延迟动画的开始。您可以BeginTime改为设置其属性。
Finally, no Storyboard is needed to animate a single property. You could call UIElement.BeginAnimationinstead.
最后,不需要 Storyboard 来为单个属性设置动画。你可以打电话UIElement.BeginAnimation代替。
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;
}
回答by Ben Watkins
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)
这是一个简单的修复,将填充行为更改为停止并添加一个事件处理程序以在动画后将不透明度值更改为 0(否则它将返回到 1)
animation.FillBehavior = FillBehavior.Stop;
animation.Completed += delegate
{
lblTest.Opacity = 0;
};
I have tested this with your code and it worked.
我已经用您的代码对此进行了测试,并且有效。
Ben
本

