是否可以通过在 Xaml 中调用来自 ViewModel 的命令的方式来处理 Storyboard.Completed 事件

Is it possible to handle the Storyboard.Completed Event in such a way that a command from the ViewModel is called in Xaml

我解决问题的方式是代码隐藏中有一个 EventHandler,然后调用 ViewModel 的相应 Command

<Storyboard x:Key="StartNewGameAnimation" RepeatBehavior="1x"
            Completed="StartAnimationCompleted">
private void StartAnimationCompleted(object sender, EventArgs e)
{
    var gameBoardViewModel = (GameBoardViewModel)this.DataContext;
    gameBoardViewModel.StartGameWhenStartanimationCompletedCommand.Execute(null);
}

此解决方案工作正常,但我想直接在 Xaml 中处理 Event 并调用 Command。这条路是否存在对我来说很重要。

您可以使用 Microsoft.Xaml.Behaviors.Wpf NuGet package that replaces the legacy Interactivity 类型。有一种 InvokeCommandAction 类型可以通过 EventTrigger.

调用命令

但是里面的直接方式Storyboard不行

<Storyboard x:Key="StartNewGameAnimation" RepeatBehavior="1x">
   <b:Interaction.Triggers>
      <b:EventTrigger EventName="Completed">
         <b:InvokeCommandAction Command="{Binding StartGameWhenStartanimationCompletedCommand}"/>
      </b:EventTrigger>
   </b:Interaction.Triggers>
</Storyboard>

它会在运行时抛出异常,因为Storyboard不能用绑定冻结。

'Microsoft.Xaml.Behaviors.Interactivity.EventTrigger' must have IsFrozen set to false to modify

解决方法是将交互块移动到父元素,例如BeginStoryboard 并使用 ElementName 绑定引用 Storyboard

<BeginStoryboard>
   <b:Interaction.Triggers>
      <b:EventTrigger EventName="Completed" SourceObject="{Binding ElementName=StartNewGameAnimation}">
         <b:InvokeCommandAction Command="{Binding StartGameWhenStartanimationCompletedCommand}"/>
      </b:EventTrigger>
   </b:Interaction.Triggers>
   <!-- ...other code. -->
   </Storyboard>
</BeginStoryboard>

根据上下文,设置 SourceName 而不是 SourceObject 也可以。

<b:EventTrigger EventName="Completed" SourceName="StartNewGameAnimation">

顺便说一下,您必须在控件中添加以下 XML 命名空间,以引用类型:

xmlns:b="http://schemas.microsoft.com/xaml/behaviors"