代码之家  ›  专栏  ›  技术社区  ›  Joe White

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

  •  10
  • Joe White  · 技术社区  · 14 年前

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

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

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

    5 回复  |  直到 14 年前
        1
  •  6
  •   Felice Pollano    14 年前

    可以通过从System.Windows.interactive.TriggerBase派生来完成此操作。 Here is an example .

        2
  •  12
  •   Gregor Slavec    13 年前

    我修改了 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);
        }
      }
    
        3
  •  6
  •   EisenbergEffect    14 年前

    Caliburn.Micro的操作机制构建在System.Windows.interactive之上。因此,您可以基于TriggerBase创建一个自定义触发器来执行任何您想要的操作,包括全局键盘手势。然后,把行动信息插入你的触发器和viola!

        4
  •  0
  •   foson    14 年前

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

        5
  •  -1
  •   bdeem    9 年前

    如果通过视图将命令封送到视图模型,则可以从视图模型控制CanExecute。我已经在多个Caliburn项目中使用了这种方法。可能不像使用交互性那样“圆滑”,但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}"/>
    

    在视图类中,将命令连接到MyView.DataContext属性中引用的视图模型。

    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