WPF:如何使用DataTrigger平滑地停止旋转动画

时间:2013-12-10 12:09:35

标签: wpf xaml animation datatrigger rotatetransform

动画几乎不会停止,图像会重置其位置,但我希望动画完成到下一个完整的360°。

有关于此的任何想法吗?

XAML代码:

<Button
    BorderThickness="0"
    Cursor="Hand"
    Command="{Binding RefreshCommand}">
    <Button.Template>
        <ControlTemplate TargetType="Button">
            <Border>
                <ContentPresenter />
            </Border>
        </ControlTemplate>
    </Button.Template>
    <Image Source="../Resources/RefreshIcon.png">
        <Image.Style>
            <Style>
                <Setter Property="Image.RenderTransform">
                    <Setter.Value>
                        <RotateTransform />
                    </Setter.Value>
                </Setter>
                <Setter Property="Image.RenderTransformOrigin" Value=".5,.5">
                </Setter>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsRefreshing}" Value="True">
                        <DataTrigger.EnterActions>
                            <BeginStoryboard Name="RotationStoryboard">
                                <Storyboard>
                                    <DoubleAnimation
                                        Storyboard.TargetProperty="RenderTransform.Angle"
                                        From="0"
                                        To="360"
                                        Duration="0:0:0.8"
                                        RepeatBehavior="Forever" />
                                </Storyboard>
                            </BeginStoryboard>
                        </DataTrigger.EnterActions>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding IsRefreshing}" Value="False">
                        <DataTrigger.EnterActions>
                            <RemoveStoryboard BeginStoryboardName="RotationStoryboard"/>
                        </DataTrigger.EnterActions>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Image.Style>
    </Image>
</Button>

最终解决方案除了必须将其放入UserControl以使其更通用之外(另请参阅下面的@Sheridans帖子和我的评论):

<Button
    BorderThickness="0"
    Cursor="Hand"
    Command="{Binding RefreshCommand}">
    <Button.Template>
        <ControlTemplate TargetType="Button">
            <Border>
                <ContentPresenter />
            </Border>
        </ControlTemplate>
    </Button.Template>
    <Image
        Name="RefreshImage"
        Source="../Resources/RefreshIcon.png"
        RenderTransformOrigin=".5,.5">
        <Image.Resources>
            <Storyboard
                x:Key="RotationStoryboard"
                Completed="RotationStoryboardCompleted">
                <DoubleAnimation
                    Storyboard.Target="{Binding ElementName=RefreshImage}"
                    Storyboard.TargetProperty="RenderTransform.Angle"
                    From="0"
                    To="360"
                    Duration="0:0:1.5">
                    <DoubleAnimation.EasingFunction>
                        <CircleEase EasingMode="EaseInOut"></CircleEase>
                    </DoubleAnimation.EasingFunction>
                </DoubleAnimation>
            </Storyboard>
        </Image.Resources>
        <Image.Style>
            <Style>
                <Setter Property="Image.RenderTransform">
                    <Setter.Value>
                        <RotateTransform />
                    </Setter.Value>
                </Setter>
                <Setter Property="Image.RenderTransformOrigin" Value=".5,.5">
                </Setter>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsRefreshing}" Value="True">
                        <DataTrigger.EnterActions>
                            <BeginStoryboard>
                                <StaticResource ResourceKey="RotationStoryboard"/>
                            </BeginStoryboard>
                        </DataTrigger.EnterActions>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Image.Style>
    </Image>
</Button>

代码背后:

public partial class SomeView
{
    public SomeView()
    {
        InitializeComponent();
    }

    private void RotationStoryboardCompleted(object sender, EventArgs e)
    {
        var viewModel = (ISomeViewModel)DataContext;
        var storyboard = (Storyboard)((ClockGroup)sender).Timeline;

        if (viewModel.IsRefreshing)
        {
            storyboard.Begin();
        }
    }
}

1 个答案:

答案 0 :(得分:1)

我不知道在XAML中有什么办法可以做到这一点,但是对于代码,你可以使用Timeline.Completed Event。如果您将一个处理程序附加到Storyboard,那么它将在完成时被调用,您可以随心所欲地执行任何操作:

<BeginStoryboard>
    <Storyboard Name="RotationStoryboard" Completed="StoryboardCompleted">
        <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Angle" From="0" 
To="360" Duration="0:0:0.8" />
    </Storyboard>
</BeginStoryboard>

在代码中:

private void StoryboardCompleted(object sender, EventArgs e)
{
    // Restart your Storyboard here each time until you want it to stop.
}

有关进一步的帮助,请参阅MSDN上链接页面中的示例。