在当前运行动画完成后停止StoryBoard

时间:2015-05-22 11:05:43

标签: wpf xaml storyboard

我希望在控制IsAnimating的属性更改为false后停止WPF StoryBoard,但我需要立即停止动画,但首先完成当前正在运行的动画循环然后停止它(我现在正在使用此XAML,但它立刻停止我的动画):

<UserControl x:Class="App.Controls.ProgressCircle"
             x:Name="me"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" >
    <Ellipse Name="Circle" Width="30" Height="30" Fill="Green" >
        <Ellipse.Style>
            <Style>
                <Style.Resources>
                    <Storyboard x:Key="Pulsing">
                        <DoubleAnimation  From="30.0" To="0.0" Duration="0:0:1" AutoReverse="True" RepeatBehavior="Forever" 
                                                      Storyboard.TargetProperty="Width" />

                        <DoubleAnimation  From="30.0" To="0.0" Duration="0:0:1" AutoReverse="True" RepeatBehavior="Forever" 
                                                      Storyboard.TargetProperty="Height" />
                    </Storyboard>
                </Style.Resources>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsAnimating, ElementName=me}" Value="True">
                        <DataTrigger.EnterActions>
                            <BeginStoryboard Name="Pulsing" Storyboard="{StaticResource Pulsing}" />
                        </DataTrigger.EnterActions>
                        <DataTrigger.ExitActions>
                            <StopStoryboard BeginStoryboardName="Pulsing"  />
                        </DataTrigger.ExitActions>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Ellipse.Style>
    </Ellipse>
</UserControl>

1 个答案:

答案 0 :(得分:2)

“快速而肮脏”的解决方案是在DataTrigger.ExitActions中启动一个新动画,该动画将高度和宽度属性设置为在整个动画开始之前的值。这看起来像这样:

<Style.Triggers>
    <DataTrigger Binding="{Binding IsAnimating, ElementName=me}" Value="True">
        <DataTrigger.EnterActions>
            <BeginStoryboard Name="Pulsing" Storyboard="{StaticResource Pulsing}" />
        </DataTrigger.EnterActions>
        <DataTrigger.ExitActions>
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Duration="0:0:1" 
                                     Storyboard.TargetProperty="Height" />
                    <DoubleAnimation Duration="0:0:1" 
                                     Storyboard.TargetProperty="Width" />
                </Storyboard>
            </BeginStoryboard>
        </DataTrigger.ExitActions>
    </DataTrigger>
</Style.Triggers>

重要的是,如果你没有在动画上设置To值,那么目标值将是依赖属性以前具有的值(本地值为30.0) case)。在这种情况下你不必停止'Pulsing'故事板,因为当你启动一个动画相同依赖属性的新故事板时会自动完成。

显然,这不是最佳解决方案,因为您没有整合Pulsing动画的当前状态(即IsAnimating设置为false时的哪个时间点)。据我所知,WPF中没有内置功能来实现这种功能,但是可以实现一个尊重所有这些信息的自定义ConstrallableStoryboardAction,并且可以在{{ 1}}而不是。检查一些Animation How-To topics in the MSDN library可能也值得您花些时间。