WPF 淡入/淡出仅运行一次
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14607868/
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 In / Out only runs once
提问by MystyxMac
I have a Style with a Storyboard and Triggers. The animation work nicely, but only once.
我有一个带有故事板和触发器的样式。动画效果很好,但只有一次。
I have 2 Storyboards FadeIn and FadeOut. In the EnterActions I start the FadeIn animation and in the ExitActions the FadeOut animation. I start the whole animation in code with
我有 2 个故事板淡入和淡出。在 EnterActions 中,我启动 FadeIn 动画,在 ExitActions 中启动 FadeOut 动画。我用代码开始整个动画
TextBlock.StartFade = true;
When i debug the above code, with every hit StartFade is False (which is correct).
当我调试上面的代码时,每次点击 StartFade 都是 False(这是正确的)。
So what do i do wrong?
那么我做错了什么?
Here is the Style in XAML. FadingTextBlock is just a custom TextBlock with a StartFade dependency property.
这是 XAML 中的样式。FadingTextBlock 只是一个带有 StartFade 依赖属性的自定义 TextBlock。
<Style TargetType="{x:Type Controls:FadingTextBlock}">
<Setter Property="Visibility" Value="Collapsed" />
<Setter Property="StartFade" Value="False" />
<Setter Property="Opacity" Value="1.0" />
<Style.Resources>
<Storyboard x:Key="FadeIn">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Controls:FadingTextBlock.Opacity)" Storyboard.TargetName="{x:Null}">
<EasingDoubleKeyFrame KeyTime="0:0:0.0" Value="0.0" />
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1.0" />
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Controls:FadingTextBlock.Visibility)" Storyboard.TargetName="{x:Null}">
<DiscreteObjectKeyFrame KeyTime="0:0:0.0" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="(Controls:FadingTextBlock.StartFade)" Storyboard.TargetName="{x:Null}">
<DiscreteBooleanKeyFrame KeyTime="0:0:1.5" Value="False" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="FadeOut">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Controls:FadingTextBlock.Opacity)" Storyboard.TargetName="{x:Null}">
<EasingDoubleKeyFrame KeyTime="0:0:0.0" Value="1.0" />
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="0.0" />
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Controls:FadingTextBlock.Visibility)" Storyboard.TargetName="{x:Null}">
<DiscreteObjectKeyFrame KeyTime="0:0:1.5" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</Style.Resources>
<Style.Triggers>
<Trigger Property="StartFade" Value="True">
<Trigger.EnterActions>
<BeginStoryboard x:Name="In" Storyboard="{StaticResource FadeIn}" />
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard x:Name="Out" Storyboard="{StaticResource FadeOut}" />
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
采纳答案by MystyxMac
I ended up using a local animation in code.
我最终在代码中使用了本地动画。
Set the TextBlock Opacity to 0 in Xaml.
在 Xaml 中将 TextBlock 不透明度设置为 0。
// Fading animation for the textblock to show that the settings are updated.
DoubleAnimation fadingAnimation = new DoubleAnimation();
fadingAnimation.From = 0;
fadingAnimation.To = 1;
fadingAnimation.Duration = new Duration(TimeSpan.FromSeconds(1.5));
fadingAnimation.AutoReverse = true;
UpdateMessage.BeginAnimation(TextBlock.OpacityProperty, fadingAnimation);
回答by Aphelion
You should stop the started storyboard(s) from playing in the exit action using the <StopStoryboard>action.
您应该使用操作停止在退出操作中播放开始的故事板<StopStoryboard>。
<Trigger Property="StartFade" Value="True">
<Trigger.EnterActions>
<StopStoryBoard BeginStoryboardName="Out"/>
<BeginStoryboard x:Name="In" Storyboard="{StaticResource FadeIn}" />
</Trigger.EnterActions>
<Trigger.ExitActions>
<StopStoryBoard BeginStoryboardName="In"/>
<BeginStoryboard x:Name="Out" Storyboard="{StaticResource FadeOut}" />
</Trigger.ExitActions>
</Trigger>
回答by Eyal Perry
I Implemented my own C# solution for this, based on @MystyxMac Extracted it to a blend behavior, which exposed a challenge..
我为此实现了自己的 C# 解决方案,基于 @MystyxMac 将其提取为混合行为,这暴露了一个挑战..
Attempting to show the same notification twice in a row will not work since the dependency property changed callback will not be called..
尝试连续两次显示相同的通知将不起作用,因为不会调用依赖属性更改回调。
I overcame this by obtaining the binding, clearing it and setting it again.
我通过获取绑定、清除它并再次设置它来克服这个问题。
public class ShowFadingTextBehavior : System.Windows.Interactivity.Behavior<TextBlock>
{
public static readonly DependencyProperty DurationProperty = DependencyProperty.Register(
"Duration", typeof(TimeSpan), typeof(ShowFadingTextBehavior), new PropertyMetadata(TimeSpan.FromSeconds(5)));
public TimeSpan Duration
{
get { return (TimeSpan)GetValue(DurationProperty); }
set { SetValue(DurationProperty, value); }
}
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text", typeof (string), typeof (ShowFadingTextBehavior), new PropertyMetadata("",OnTextChanged));
private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var b = (ShowFadingTextBehavior) d;
var text = (string) e.NewValue;
if(string.IsNullOrEmpty(text))
return;
b.Show(text);
}
private void Show(string text)
{
var textBlock = AssociatedObject;
if(textBlock==null)
return;
textBlock.Text = text;
if(textBlock.Visibility==Visibility.Visible)
return;
textBlock.Visibility = Visibility.Visible;
var a = new DoubleAnimation
{
From = 1.0,
To = 0.0,
FillBehavior = FillBehavior.Stop,
BeginTime = TimeSpan.FromSeconds(1),
Duration = new Duration(Duration)
};
var storyboard = new Storyboard();
storyboard.Children.Add(a);
Storyboard.SetTarget(a, textBlock);
Storyboard.SetTargetProperty(a, new PropertyPath(UIElement.OpacityProperty));
storyboard.Completed += delegate
{
textBlock.Visibility = Visibility.Collapsed;
textBlock.Opacity = 1.0;
var binding = BindingOperations.GetBinding(this, TextProperty);
if(binding==null)
return;
ClearValue(TextProperty);
BindingOperations.SetBinding(this, TextProperty, binding);
};
storyboard.Begin();
}
public string Text
{
get { return (string) GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
}

