WPF 中的键盘快捷键
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1361350/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Keyboard shortcuts in WPF
提问by Benjol
I know about using _
instead of &
, but I'm looking at all the Ctrl+ type shortcuts.
我知道使用_
而不是&
,但我正在查看所有Ctrl+ 类型的快捷方式。
Ctrl+Zfor undo, Ctrl+Sfor save, etc.
Ctrl+Z用于撤消,Ctrl+S用于保存等。
Is there a 'standard' way for implementing these in WPF applications? Or is it a case of roll your own and wire them up to whatever command/control?
是否有在 WPF 应用程序中实现这些的“标准”方法?或者是自己动手并将它们连接到任何命令/控制?
回答by Abby Fichtner
I understand the standard way is by creating commands and then adding your shortcut keys to them as InputGestures.
我了解标准方法是创建命令,然后将快捷键作为 InputGestures 添加到它们中。
This enables the shortcut keys to work even if they're not hooked up to any controls. And since menu items understand keyboard gestures, they'll automatically display your shortcut key in the menu items text, if you hook that command up to your menu item.
这使快捷键即使没有连接到任何控件也能工作。由于菜单项理解键盘手势,如果您将该命令与菜单项挂钩,它们将自动在菜单项文本中显示您的快捷键。
Create static attribute to hold a command (preferably as a property in a static class you create for commands - but for a simple example, just using a static attribute in window.cs):
public static RoutedCommand MyCommand = new RoutedCommand();
Add the shortcut key(s) that should invoke method:
MyCommand.InputGestures.Add(new KeyGesture(Key.S, ModifierKeys.Control));
Create a command binding that points to your method to call on execute. Put these in the command bindings for the UI element under which it should work for (e.g., the window) and the method:
<Window.CommandBindings> <CommandBinding Command="{x:Static local:MyWindow.MyCommand}" Executed="MyCommandExecuted"/> </Window.CommandBindings> private void MyCommandExecuted(object sender, ExecutedRoutedEventArgs e) { ... }
创建静态属性以保存命令(最好作为您为命令创建的静态类中的属性 - 但对于一个简单的示例,只需在 window.cs 中使用静态属性):
public static RoutedCommand MyCommand = new RoutedCommand();
添加应该调用方法的快捷键:
MyCommand.InputGestures.Add(new KeyGesture(Key.S, ModifierKeys.Control));
创建一个命令绑定,指向您的方法以在执行时调用。将这些放在它应该在其下工作的 UI 元素(例如,窗口)和方法的命令绑定中:
<Window.CommandBindings> <CommandBinding Command="{x:Static local:MyWindow.MyCommand}" Executed="MyCommandExecuted"/> </Window.CommandBindings> private void MyCommandExecuted(object sender, ExecutedRoutedEventArgs e) { ... }
回答by oliwa
I found this to be exactly what I was looking for related to key binding in WPF:
我发现这正是我正在寻找的与 WPF 中的键绑定相关的内容:
<Window.InputBindings>
<KeyBinding Modifiers="Control"
Key="N"
Command="{Binding CreateCustomerCommand}" />
</Window.InputBindings>
See blog post MVVM CommandReference and KeyBinding
回答by Shahid Neermunda
Try this code...
试试这个代码...
First create a RoutedComand object
首先创建一个RoutedComand对象
RoutedCommand newCmd = new RoutedCommand();
newCmd.InputGestures.Add(new KeyGesture(Key.N, ModifierKeys.Control));
CommandBindings.Add(new CommandBinding(newCmd, btnNew_Click));
回答by Anvaka
It depends on where you want to use those.
这取决于你想在哪里使用它们。
TextBoxBase
-derived controls already implement those shortcuts. If you want to use custom keyboard shortcuts you should take a look on Commands and Input gestures. Here is a small tutorial from Switch on the Code: WPF Tutorial - Command Bindings and Custom Commands
TextBoxBase
- 派生控件已经实现了这些快捷方式。如果您想使用自定义键盘快捷键,您应该查看命令和输入手势。这是来自Switch on the Code 的一个小教程:WPF 教程 - 命令绑定和自定义命令
回答by Ayo I
Documenting this answer for others, as there is a much simpler way to do this that is rarely referenced, and doesn't require touching the XAML at all.
为其他人记录这个答案,因为有一种更简单的方法可以做到这一点,很少被引用,并且根本不需要接触 XAML。
To link a keyboard shortcut, in the Window constructor simply add a new KeyBinding to the InputBindings collection. As the command, pass in your arbitrary command class that implements ICommand. For the execute method, simply implement whatever logic you need. In my example below, my WindowCommand class takes a delegate that it will execute whenever invoked. When I construct the new WindowCommand to pass in with my binding, I simply indicate in my initializer, the method that I want the WindowCommand to execute.
要链接键盘快捷键,只需在 Window 构造函数中向 InputBindings 集合添加一个新的 KeyBinding。作为命令,传入实现 ICommand 的任意命令类。对于 execute 方法,只需实现您需要的任何逻辑。在下面的示例中,我的 WindowCommand 类采用一个委托,无论何时调用它都会执行该委托。当我构造新的 WindowCommand 以通过我的绑定传入时,我只需在我的初始值设定项中指明我希望 WindowCommand 执行的方法。
You can use this pattern to come up with your own quick keyboard shortcuts.
您可以使用此模式想出自己的快速键盘快捷键。
public YourWindow() //inside any WPF Window constructor
{
...
//add this one statement to bind a new keyboard command shortcut
InputBindings.Add(new KeyBinding( //add a new key-binding, and pass in your command object instance which contains the Execute method which WPF will execute
new WindowCommand(this)
{
ExecuteDelegate = TogglePause //REPLACE TogglePause with your method delegate
}, new KeyGesture(Key.P, ModifierKeys.Control)));
...
}
Create a simple WindowCommand class which takes an execution delegate to fire off any method set on it.
创建一个简单的 WindowCommand 类,它使用一个执行委托来触发在其上设置的任何方法。
public class WindowCommand : ICommand
{
private MainWindow _window;
//Set this delegate when you initialize a new object. This is the method the command will execute. You can also change this delegate type if you need to.
public Action ExecuteDelegate { get; set; }
//You don't have to add a parameter that takes a constructor. I've just added one in case I need access to the window directly.
public WindowCommand(MainWindow window)
{
_window = window;
}
//always called before executing the command, mine just always returns true
public bool CanExecute(object parameter)
{
return true; //mine always returns true, yours can use a new CanExecute delegate, or add custom logic to this method instead.
}
public event EventHandler CanExecuteChanged; //i'm not using this, but it's required by the interface
//the important method that executes the actual command logic
public void Execute(object parameter)
{
if (ExecuteDelegate != null)
{
ExecuteDelegate();
}
else
{
throw new InvalidOperationException();
}
}
}
回答by Nik
I had a similar problem and found @aliwa's answer to be the most helpful and most elegant solution; however, I needed a specific key combination, Ctrl+ 1. Unfortunately I got the following error:
我遇到了类似的问题,发现@aliwa 的答案是最有帮助和最优雅的解决方案;但是,我需要一个特定的组合键Ctrl+ 1。不幸的是,我收到以下错误:
'1' cannot be used as a value for 'Key'. Numbers are not valid enumeration values.
“1”不能用作“Key”的值。数字不是有效的枚举值。
With a bit of further search, I modified @aliwa's answer to the following:
通过进一步搜索,我修改了@aliwa 对以下内容的回答:
<Window.InputBindings>
<KeyBinding Gesture="Ctrl+1" Command="{Binding MyCommand}"/>
</Window.InputBindings>
I found this to work great for pretty well any combination I needed.
我发现这非常适合我需要的任何组合。
回答by plaasmeisie
VB.NET:
VB.NET:
Public Shared SaveCommand_AltS As New RoutedCommand
Inside the loadedevent:
在加载的事件中:
SaveCommand_AltS.InputGestures.Add(New KeyGesture(Key.S, ModifierKeys.Control))
Me.CommandBindings.Add(New CommandBinding(SaveCommand_AltS, AddressOf Me.save))
No XAML is needed.
不需要 XAML。
回答by Sebastian Hübner
Although the top answers are correct, I personally like to work with attached properties to enable the solution to be applied to any UIElement
, especially when the Window
is not aware of the element that should be focused. In my experience I often see a composition of several view models and user controls, where the window is often nothing more that the root container.
尽管顶级答案是正确的,但我个人喜欢使用附加属性来使解决方案适用于任何UIElement
,尤其是当Window
不知道应该关注的元素时。根据我的经验,我经常看到几个视图模型和用户控件的组合,其中窗口通常只是根容器。
Snippet
片段
public sealed class AttachedProperties
{
// Define the key gesture type converter
[System.ComponentModel.TypeConverter(typeof(System.Windows.Input.KeyGestureConverter))]
public static KeyGesture GetFocusShortcut(DependencyObject dependencyObject)
{
return (KeyGesture)dependencyObject?.GetValue(FocusShortcutProperty);
}
public static void SetFocusShortcut(DependencyObject dependencyObject, KeyGesture value)
{
dependencyObject?.SetValue(FocusShortcutProperty, value);
}
/// <summary>
/// Enables window-wide focus shortcut for an <see cref="UIElement"/>.
/// </summary>
// Using a DependencyProperty as the backing store for FocusShortcut. This enables animation, styling, binding, etc...
public static readonly DependencyProperty FocusShortcutProperty =
DependencyProperty.RegisterAttached("FocusShortcut", typeof(KeyGesture), typeof(AttachedProperties), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None, new PropertyChangedCallback(OnFocusShortcutChanged)));
private static void OnFocusShortcutChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is UIElement element) || e.NewValue == e.OldValue)
return;
var window = FindParentWindow(d);
if (window == null)
return;
var gesture = GetFocusShortcut(d);
if (gesture == null)
{
// Remove previous added input binding.
for (int i = 0; i < window.InputBindings.Count; i++)
{
if (window.InputBindings[i].Gesture == e.OldValue && window.InputBindings[i].Command is FocusElementCommand)
window.InputBindings.RemoveAt(i--);
}
}
else
{
// Add new input binding with the dedicated FocusElementCommand.
// see: https://gist.github.com/shuebner20/349d044ed5236a7f2568cb17f3ed713d
var command = new FocusElementCommand(element);
window.InputBindings.Add(new InputBinding(command, gesture));
}
}
}
With this attached property you can define a focus shortcut for any UIElement. It will automatically register the input binding at the window containing the element.
使用此附加属性,您可以为任何 UIElement 定义焦点快捷方式。它会在包含该元素的窗口中自动注册输入绑定。
Usage (XAML)
用法 (XAML)
<TextBox x:Name="SearchTextBox"
Text={Binding Path=SearchText}
local:AttachedProperties.FocusShortcutKey="Ctrl+Q"/>
Source code
源代码
The full sample including the FocusElementCommand implementation is available as gist: https://gist.github.com/shuebner20/c6a5191be23da549d5004ee56bcc352d
包括 FocusElementCommand 实现的完整示例可作为要点获得:https://gist.github.com/shuebner20/c6a5191be23da549d5004ee56bcc352d
Disclaimer: You may use this code everywhere and free of charge. Please keep in mind, that this is a sample that is not suitable for heavy usage. For example, there is no garbage collection of removed elements because the Command will hold a strong reference to the element.
免责声明:您可以在任何地方免费使用此代码。请记住,这是一个不适合大量使用的示例。例如,没有对已删除元素的垃圾回收,因为 Command 将持有对该元素的强引用。
回答by Ji?í Skála
How to associate the command with a MenuItem
:
如何将命令与 a 关联MenuItem
:
<MenuItem Header="My command" Command="{x:Static local:MyWindow.MyCommand}"/>