如何重启WPF的Storyboard动画,实现控件可见时自动重新播放?
WPF 提示文本闪烁动画单次触发问题修复
设置快捷键触发UI提示文本闪烁后消失的功能时,遇到Storyboard仅在整个生命周期内触发一次的问题:对应Completed事件仅触发一次,后续按下快捷键时承载TextBlock的Grid虽会变为可见,但动画不再播放,Completed事件也不会触发。
需求目标:每次Grid变为可见时,动画都能从头开始重新播放,播放完成后自动将Grid的可见性设置为隐藏。
原有问题代码
<Grid Visibility="{Binding InfoTextVisible, ElementName=MyMainWindow}"> <Grid.Triggers> <EventTrigger RoutedEvent="Grid.Loaded"> <BeginStoryboard> <Storyboard Completed="InfoTextAnimation_Completed" FillBehavior="Stop"> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Duration="0:0:1" Completed="DoubleAnimationUsingKeyFrames_Completed"> <SplineDoubleKeyFrame KeyTime="0:0:00.00" Value="0"/> <SplineDoubleKeyFrame KeyTime="0:0:01.00" Value="1"/> <SplineDoubleKeyFrame KeyTime="0:0:01.50" Value="0"/> </DoubleAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </EventTrigger> </Grid.Triggers> <TextBlock Text="{Binding InfoText, ElementName=MyMainWindow}" Name="timoti" Foreground="White" FontSize="50" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/> </Grid>
问题原因
原有代码使用Grid.Loaded路由事件作为触发器,该事件仅在Grid首次加载到视觉树时触发一次,因此后续修改Grid可见性时不会再次触发动画。
优化后代码
<Grid Visibility="{Binding InfoTextVisible, ElementName=MyMainWindow}"> <Grid.Style> <Style TargetType="Grid"> <Style.Triggers> <Trigger Property="Visibility" Value="Visible"> <Trigger.EnterActions> <BeginStoryboard x:Name="SpinStoryboard"> <Storyboard> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Duration="0:0:1"> <SplineDoubleKeyFrame KeyTime="0:0:00.00" Value="0"/> <SplineDoubleKeyFrame KeyTime="0:0:01.00" Value="1"/> <SplineDoubleKeyFrame KeyTime="0:0:01.50" Value="0"/> </DoubleAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0:0:02.00" Value="{x:Static Visibility.Hidden}"/> </ObjectAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </Trigger.EnterActions> <Trigger.ExitActions> <StopStoryboard BeginStoryboardName="SpinStoryboard"></StopStoryboard> </Trigger.ExitActions> </Trigger> </Style.Triggers> </Style> </Grid.Style> <TextBlock Text="{Binding InfoText, ElementName=MyMainWindow}" Name="timoti" Foreground="White" FontSize="50" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/> </Grid>
优化说明
- 触发器改为监听
Visibility属性变化,每次Grid变为Visible状态时都会触发EnterActions,重新启动动画 - 移除了代码后端的Completed事件依赖,直接在动画末尾添加ObjectAnimationUsingKeyFrames,自动将Grid可见性设为Hidden
- 新增ExitActions,当Grid退出可见状态时停止正在运行的动画,避免状态冲突,保证下次触发时动画可以正常从头播放
内容的提问来源于stack exchange,提问作者Joan Venge
相关产品推荐
相关产品推荐

