如何在动画完成后正确执行命令?

时间:2016-03-31 07:33:58

标签: wpf mvvm

我有一个按钮如下:

<Button x:Name ="Btn_Import" Grid.Row="33" Grid.Column="15" Grid.ColumnSpan="36" Grid.RowSpan="36" >
            <Button.Template>
                <ControlTemplate>
                    <Grid RenderTransformOrigin="0.5,0.5" x:Name="bg">
                        <Image x:Name ="import_image" Source="{Binding ImportBtnBaseImagePath}"/>

                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="import_image" Property="Source" Value="{Binding ImportBtnOverImagePath}" />
                        </Trigger>

                        <Trigger Property="ButtonBase.IsPressed"  Value ="True">
                            <!-- press effect -->
                            <Setter TargetName="bg" Property="RenderTransform">
                                <Setter.Value>
                                    <ScaleTransform ScaleX="0.9" ScaleY="0.9"/>
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Button.Template>

            <Button.Triggers>
                <EventTrigger RoutedEvent="PreviewMouseDown" >
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetName="Studio" Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:2" >
                                <i:Interaction.Triggers>
                                    <i:EventTrigger EventName="Completed">
                                        <i:InvokeCommandAction Command="{Binding NavigateCommand}" CommandParameter="ImportButtonClickParmeters" />
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </DoubleAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Button.Triggers>

        </Button>

我希望此按钮可以将某个其他控件上的动画分解为淡出2秒,然后在动画完成后通过“导航命令”导航到其他视图。但是我收到以下错误:

  

附加信息:类型的指定值   &#39; System.Windows.Interactivity.EventTrigger&#39;必须将IsFrozen设置为   false修改。

1 个答案:

答案 0 :(得分:3)

您的问题取决于众所周知的bug。不幸的是,我发现common solution在这种情况下不能正常工作。

无论如何,如果您希望保持您的应用程序符合MVVM,我建议您创建一个&#34;假的&#34;动画,其任务是执行命令。当然,这个动画必须是故事板中的最后一个动画。

这是CommandFakeAnimation代码:

public class CommandFakeAnimation : AnimationTimeline
{
    public static readonly DependencyProperty CommandProperty =
        DependencyProperty.Register("Command", typeof(ICommand), typeof(CommandFakeAnimation), new UIPropertyMetadata(null));

    public static readonly DependencyProperty CommandParameterProperty =
        DependencyProperty.Register("CommandParameter", typeof(object), typeof(CommandFakeAnimation), new PropertyMetadata(null));

    public CommandFakeAnimation()
    {
        Completed += new EventHandler(CommandAnimation_Completed);
    }

    public ICommand Command
    {
        get
        {
            return (ICommand)GetValue(CommandProperty);
        }
        set
        {
            SetValue(CommandProperty, value);
        }
    }

    public object CommandParameter
    {
        get 
        {
            return GetValue(CommandParameterProperty);
        }
        set
        {
            SetValue(CommandParameterProperty, value);
        }
    }

    private void CommandAnimation_Completed(object sender, EventArgs e)
    {
        if (Command != null && Command.CanExecute(CommandParameter))
        {
            Command.Execute(CommandParameter);
        }
    }

    protected override Freezable CreateInstanceCore()
    {
        return new CommandFakeAnimation();
    }

    public override Type TargetPropertyType
    {
        get
        {
            return typeof(Object);
        }
    }

    public override object GetCurrentValue(object defaultOriginValue, object defaultDestinationValue, AnimationClock animationClock)
    {
        return defaultOriginValue;
    }
}

如您所见,您可以将此动画应用于您希望的任何依赖属性,因为它不会更改其值。它只是在完成后执行命令。

现在我们可以在XAML中使用新动画:

<Button.Triggers>
    <EventTrigger RoutedEvent="PreviewMouseDown">
        <BeginStoryboard>
            <Storyboard>
                <DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:2" />
                <local:CommandFakeAnimation Duration="0:0:0" Command="{Binding Path=YourCommand, Mode=OneWay}"
                                            CommandParameter="{Binding Path=YourParameter, Mode=OneWay}" 
                                            Storyboard.TargetProperty="Opacity" />
            </Storyboard>
        </BeginStoryboard>
    </EventTrigger>
</Button.Triggers>

我希望它可以帮到你。