应用场景
给应用添加快捷键是很常见的场景,WPF下的一般做法是Window下添加 KeyBinding 。
但是WPF Prism模块化之后,有时候我们需要给某一个模块添加快捷键,本文主要讨论这种场景下的一种实践。
代码
参考链接 https://stackoverflow.com/a/42974477/14124583
基本思路通过 Behavior 找到控件的父窗体,添加 PreviewKeyDown 事件处理
修改了参考链接的代码来支持单键快捷键。
C#代码
public class KeyboardShortcutBehavior : Behavior<FrameworkElement>
{
private Window _parentWindow;
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register(nameof(Command), typeof(ICommand),
typeof(KeyboardShortcutBehavior), new FrameworkPropertyMetadata(null));
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
public static readonly DependencyProperty ModifierKeyProperty =
DependencyProperty.Register(nameof(ModifierKey), typeof(ModifierKeys),
typeof(KeyboardShortcutBehavior), new FrameworkPropertyMetadata(ModifierKeys.None));
public ModifierKeys ModifierKey
{
get { return (ModifierKeys)GetValue(ModifierKeyProperty); }
set { SetValue(ModifierKeyProperty, value); }
}
public static readonly DependencyProperty KeyProperty =
DependencyProperty.Register(nameof(Key), typeof(Key),
typeof(KeyboardShortcutBehavior), new FrameworkPropertyMetadata(Key.None));
public Key Key
{
get { return (Key)GetValue(KeyProperty); }
set { SetValue(KeyProperty, value); }
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Loaded += AssociatedObject_Loaded;
AssociatedObject.Unloaded += AssociatedObject_Unloaded;
}
private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
{
_parentWindow = Window.GetWindow(AssociatedObject);
if (_parentWindow != null)
{
_parentWindow.PreviewKeyDown += ParentWindow_PreviewKeyDown;
}
}
private void ParentWindow_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (Command != null && Key != Key.None && Keyboard.Modifiers == ModifierKey && e.Key == Key)
Command.Execute(null);
}
private void AssociatedObject_Unloaded(object sender, RoutedEventArgs e)
{
if (_parentWindow != null)
{
_parentWindow.PreviewKeyDown -= ParentWindow_PreviewKeyDown;
}
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.Loaded -= AssociatedObject_Loaded;
AssociatedObject.Unloaded -= AssociatedObject_Loaded;
}
}
xaml代码
<UserControl ...
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
...>
<behaviors:KeyboardShortcutBehavior Key="A" Command="{Binding Command0}" />
<behaviors:KeyboardShortcutBehavior Key="A" ModifierKey="Ctrl" Command="{Binding Command1}" />
<Grid>
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="24"
Text="Message" />
</Grid>
</UserControl>