如何在Caliburn.Micro中绑定关键手势?

时间:2010-11-15 04:07:01

标签: wpf keyboard caliburn.micro

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

例如,我想实现一个标签式界面,我希望我的ShellViewModel有一个NewTab方法,用户应该可以通过按键盘上的Ctrl + T来调用它。

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

5 个答案:

答案 0 :(得分:12)

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

<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);
    }
  }

答案 1 :(得分:6)

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

答案 2 :(得分:6)

您可以通过从System.Windows.Interactivity.TriggerBase派生来实现。 Here is an example

答案 3 :(得分:0)

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

答案 4 :(得分:-1)

如果通过View to the View Model编组命令,则可以从View Model控制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