10

如何让 Caliburn.Micro 将按键手势映射到 ViewModel 上的操作方法?

例如,我想实现一个选项卡式界面,并且我希望我的 ShellViewModel 有一个 NewTab 方法,用户应该能够通过按键盘上的 Ctrl+T 来调用该方法。

我知道完整的 Caliburn 框架支持手势,但是如何使用 Caliburn.Micro 来做到这一点?是否有某种方法可以将操作绑定到 RoutedCommand(因为 RoutedCommands 已经支持输入手势)?或者其他方式来获得手势支持?

4

5 回答 5

12

我修改了示例以启用对全局键绑定的支持。您只需将以下代码添加到您的视图中:

<i:Interaction.Triggers>
        <common:InputBindingTrigger>
            <common:InputBindingTrigger.InputBinding>
                <KeyBinding Modifiers="Control" Key="D"/>
            </common:InputBindingTrigger.InputBinding>
            <cl:ActionMessage MethodName="DoTheMagic"/>
        </common:InputBindingTrigger>
    </i:Interaction.Triggers>

并且每当按下 Ctr+D 时,都会执行 DoTheMagic 方法。这是修改后的 InputBindingTrigger 代码:

public class InputBindingTrigger : TriggerBase<FrameworkElement>, ICommand
  {
    public static readonly DependencyProperty InputBindingProperty =
      DependencyProperty.Register("InputBinding", typeof (InputBinding)
        , typeof (InputBindingTrigger)
        , new UIPropertyMetadata(null));

    public InputBinding InputBinding
    {
      get { return (InputBinding) GetValue(InputBindingProperty); }
      set { SetValue(InputBindingProperty, value); }
    }

    public event EventHandler CanExecuteChanged = delegate { };

    public bool CanExecute(object parameter)
    {
      // action is anyway blocked by Caliburn at the invoke level
      return true;
    }

    public void Execute(object parameter)
    {
      InvokeActions(parameter);
    }

    protected override void OnAttached()
    {
      if (InputBinding != null)
      {
        InputBinding.Command = this;        
        AssociatedObject.Loaded += delegate {
          var window = GetWindow(AssociatedObject);
          window.InputBindings.Add(InputBinding);
        };
      }
      base.OnAttached();
    }

    private Window GetWindow(FrameworkElement frameworkElement)
    {
      if (frameworkElement is Window)
        return frameworkElement as Window;

      var parent = frameworkElement.Parent as FrameworkElement;      
      Debug.Assert(parent != null);

      return GetWindow(parent);
    }
  }
于 2011-11-23T16:58:19.897 回答
6

Caliburn.Micro 的 Actions 机制建立在 System.Windows.Interactivity 之上。因此,您可以创建一个基于 TriggerBase 的自定义触发器来做任何您想做的事情,包括全局键盘手势。然后,只需将 ActionMessage 插入您的触发器和中提琴!

于 2010-11-15T12:52:14.900 回答
6

您可以通过从 System.Windows.Interactivity.TriggerBase 派生来实现。这是一个例子

于 2011-05-02T17:46:53.593 回答
0

从 Caliburn 的 ActionMessage(它是一个 TriggerAction)继承并将派生的触发器附加到 XAML 中的 KeyDown 事件并设置 ActionMessage.MethodName 属性。将属性添加到您要查找的组合键的派生触发器,并覆盖 Invoke 方法以按该组合键进行过滤,如果键匹配,则调用 base.Invoke(...)。

于 2011-07-08T16:59:48.243 回答
-1

如果通过视图将命令编组到视图模型,则可以从视图模型控制 CanExecute。我一直在多个 Caliburn 项目中使用这种方法。可能不像使用 Interactivity 那样“光滑”,但 CanExecute 有效。

<UserControl x:Class="MyView"
      ...
      Name="View"
>

  <UserControl.InputBindings>
    <KeyBinding Key="F5" 
                Command="{Binding RefreshCommand, ElementName=View, Mode=OneWay}" />
  </UserControl.InputBindings>

  <Button Command="{Binding Path=RefreshCommand, ElementName=View, Mode=OneWay}"/>

在您的 View 类中,您将命令连接到 MyView.DataContext 属性中引用的 View Model。

Class MyView

    Public Property RefreshCommand As _
    New RelayCommand(AddressOf Refresh,
                     Function()
                         If ViewModel Is Nothing Then
                             Return False
                         Else
                             Return ViewModel.CanRefresh
                         End If
                     End Function)

    Private Sub Refresh()
        ViewModel.Refresh()
    End Sub

    Private ReadOnly Property ViewModel As MyViewModel
        Get
            Return DirectCast(DataContext, MyViewModel)
        End Get
    End Property

End Class
于 2016-04-21T14:54:47.763 回答