如何使用Caliburn.Micro将键盘手势映射到ViewModel上的操作方法?
例如,我想要实现一个选项卡界面,并且我希望我的ShellViewModel拥有一个NewTab方法,用户应该能够通过按下键盘上的Ctrl+T来调用该方法。
我知道完整的Caliburn框架支持手势,但是如何使用Caliburn.Micro来实现呢?是否有一种方式可以将操作绑定到路由命令(RoutedCommand)(因为RoutedCommands已经支持输入手势)?或者其他获得手势支持的方式?
如何使用Caliburn.Micro将键盘手势映射到ViewModel上的操作方法?
例如,我想要实现一个选项卡界面,并且我希望我的ShellViewModel拥有一个NewTab方法,用户应该能够通过按下键盘上的Ctrl+T来调用该方法。
我知道完整的Caliburn框架支持手势,但是如何使用Caliburn.Micro来实现呢?是否有一种方式可以将操作绑定到路由命令(RoutedCommand)(因为RoutedCommands已经支持输入手势)?或者其他获得手势支持的方式?
我修改了示例,以支持全局键绑定。 你只需要将以下代码添加到你的视图中:
<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>
每当按下Ctrl+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);
}
}
Caliburn.Micro的Actions机制是基于System.Windows.Interactivity开发的。所以,您可以基于TriggerBase创建自定义触发器来完成任何操作,包括全局键盘手势。然后,将ActionMessage插入到触发器中即可!
如果您通过视图将命令传递到视图模型,您可以从视图模型控制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}"/>
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