定义MenuItem快捷键

我需要一个简单的方法来设置菜单项的快捷方式。

但是,这不能使用快捷方式,只需点击:

<MenuItem Header="Editar"> <MenuItem Header="Procurar" Name="MenuProcurar" InputGestureText="Ctrl+F" Click="MenuProcurar_Click"> <MenuItem.ToolTip> <ToolTip> Procurar </ToolTip> </MenuItem.ToolTip> </MenuItem> </MenuItem> 

我正在使用WPF 4.0

您需要使用KeyBindings (和CommandBindings如果您(重新)使用RoutedCommandsApplicationCommands类中的那些RoutedCommands ))来执行快捷方式的控制。

例如

 <Window.CommandBindings> <CommandBinding Command="New" Executed="CommandBinding_Executed" /> </Window.CommandBindings> <Window.InputBindings> <KeyBinding Key="N" Modifiers="Control" Command="New"/> </Window.InputBindings> 

对于自定义的RoutedCommands

 static class CustomCommands { public static RoutedCommand DoStuff = new RoutedCommand(); } 

用法:

 <Window ... xmlns:local="clr-namespace:MyNamespace"> <Window.CommandBindings> <CommandBinding Command="local:CustomCommands.DoStuff" Executed="DoStuff_Executed" /> </Window.CommandBindings> <Window.InputBindings> <KeyBinding Key="D" Modifiers="Control" Command="local:CustomCommands.DoStuff"/> </Window.InputBindings> ... </Window> 

(实现ICommand接口通常更方便,而不是使用RoutedCommands可以有一个构造方法,这个构造方法需要委托ExecuteCanExecute来轻松创build执行不同事情的命令,这种实现通常被称为DelegateCommandRelayCommand 。不需要CommandBindings 。)

HB是对的…我只是想增加更多的精度。

删除MenuItem上的Click事件并将其与Command关联。

1 – 添加/创build您的命令:

  <Window.CommandBindings> <CommandBinding Command="Open" Executed="OpenCommandBinding_Executed"></CommandBinding> <CommandBinding Command="SaveAs" Executed="SaveAsCommandBinding_Executed"></CommandBinding> </Window.CommandBindings> 

这些命令引用了下面的代码

 private void OpenCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e) { Open();//Implementation of open file } private void SaveAsCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e) { SaveAs();//Implementation of saveAs } 

2 – 将命令与想要的键相关联:

 <Window.InputBindings> <KeyBinding Key="O" Modifiers="Control" Command="Open"></KeyBinding> <KeyBinding Key="S" Modifiers="Control" Command="SaveAs"></KeyBinding> </Window.InputBindings> 

3 – 最后为你指定菜单项(InpuGestureText只是一个装饰文本):

 <Menu Name="menu1" > <MenuItem Header="_File" > <MenuItem Name="menuOpen" Header="_Open..." Command="Open" InputGestureText="Ctrl+O" /> <MenuItem Name="menuSaveAs" Header="_Save as..." Command="SaveAs" InputGestureText="Ctrl+S" /> </MenuItem> </Menu> 

这样多个input可以被关联到相同的命令。

在我看来,只要在标题处使用_就简单多了。 这将自动创build所需的热键。

例如:

 <MenuItem Header="_Editar"> <MenuItem Header="_Procurar" Name="MenuProcurar" InputGestureText="Ctrl+F" Click="MenuProcurar_Click"> <MenuItem.ToolTip> <ToolTip> Procurar </ToolTip> </MenuItem.ToolTip> </MenuItem> </MenuItem> 

我被Windows.Forms& gulp VB 6所偏爱,所以我同意Jonathan和Jase的观点,要有一种更直接的/程序化的方法来静态连接不一定是CommandBindings事件处理程序。 而且,我想。

我相信,在这个MSDN博客文章中可以find一个很好的使用非CommandBinding处理程序的教程,但强调button。 我会蒸馏和目标MenuItem s …

创buildICommand

首先,创build一个实现ICommand的类。 当然,如果你愿意的话,你可以把它放在你的MainWindow.xaml.cs文件中,让你的演示代码非常简单。 您可能想在CanExecute想要dis / en / able菜单项时使CanExecute变得更加复杂,但是现在,我们将始终启用我们的菜单项。

 public class HelloWorldCommand : ICommand { public void Execute(object parameter) { MessageBox.Show(@"""Hello, world!"" from " + (parameter ?? "somewhere secret").ToString()); } public bool CanExecute(object parameter) { return true; } public event EventHandler CanExecuteChanged; } 

正如教程有帮助地指出的那样,你可以从任何地方调用这个命令,例如…

 var hwc = new HelloWorldCommand(); if (hwc.CanExecute(this)) hwc.Execute(this); 

在窗口中声明你的命令

因此,让我们为HelloWorldCommand添加一种“声明”到我们的窗口,以便我们稍后使用它。 在Window标签内部,将该命令注册为资源:

 <Window.Resources> <local:HelloWorldCommand x:Key="hwc"/> </Window.Resources> 

现在我们有了一个简洁的快捷方式来链接到这个“本地命名空间”命令, "hwc" ,尽pipe你明显可以使用任何你想要的string。 我们将在xaml中使用它。

连接(并重新使用!)命令

让我们将我们的MenuItem添加到我们的xaml。 我已经用DockPanelreplace了Grid ,因为对于我来说,最简单的方法是使用等距的小部件来填充Window ,尽pipe我已经把所有其余的UI都留下了。

注意Command="{StaticResource hwc}"到每个MenuItem声明中。 关键是在那里的hwc – 记住,这是我们在Window级别设置的HelloWorldCommand的快捷方式。 当然, StaticResource说只是查看Window的资源。 我们没有任何约束力。 我们只是使用我们的捷径。

 <DockPanel LastChildFill="True"> <Menu DockPanel.Dock="Top"> <MenuItem Header="_File"> <MenuItem Header="_Open" Command="{StaticResource hwc}" > <MenuItem.CommandParameter> <!-- so you could make this object as complex as you wanted, like, say, your entire Window. See magic incantation, below. --> <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType=Window}" /> </MenuItem.CommandParameter> </MenuItem> <MenuItem Header="_Close" Command="{StaticResource hwc}" CommandParameter="Close" InputGestureText="Ctrl+G" /> <MenuItem Header="_Save" Command="{StaticResource hwc}" CommandParameter="Save" /> <Separator /> <MenuItem Header="_Quit" Command="{StaticResource hwc}" CommandParameter="Quit" /> </MenuItem> </DockPanel> 

CommandParameters来区分事件源

请注意, 我们使用相同的命令的一切! 但是,我们怎么能知道哪个小部件抛出事件? 为此,您需要使用CommandParameter – 记住我们的Execute方法的签名: Execute(object parameter) 。 该CommandParameter参数是我们可以用来知道如何处理事件。 尝试运行这个并注意MessageBox将使用CommandParameter任何内容来让你知道事件的来源。 我们正在手动完成这一切,但这不是太糟糕。

还要注意,你可以使这些对象像你想的那样复杂。 您可以使用MenuItem标记中的属性来定义参数,或者可以使用“Real” <MenuItem.CommandParameter>标记(如上面的“打开”菜单项中)来定义复杂的事物。 在这种情况下, 我们传递了整个父Window对象 ,这是最简单的(尽pipe不是最干净的)方法将VB6-ish上下文放入事件处理程序代码中。

MenuItem添加键盘快捷键(又名“回答OP”)

现在我们终于可以回答原来的问题了! 让我们终于连线Close菜单项的键盘快捷键。 你会注意到我们已经声明了一个InputGestureTextInputGestureText本身只是一个整体 。 如果我们过于挑剔,我们可以争辩说创build键盘快捷方式的机制与MenuItem根本没有任何直接的内在联系!

我们需要替代(或者另外)在Window级别注册一个Ctrl-G的侦听器来捕捉按键。 所以在你的Window标签的顶层,插入这个(基本上来自这里 ):

 <Window.InputBindings> <KeyBinding Modifiers="Control" Key="G" Command="{StaticResource hwc}" CommandParameter="window input binding" /> </Window.InputBindings> 

请注意,您可以将CommandParameter标签放在您的KeyBinding是将其从一个自我closures的XML片段移动到“真实”打开和closuresKeyBinding标签。

我们完成了。 运行你的应用程序,然后按下Ctrl-G。 Whaddup。

很简单,一旦你拥有了玩家,而且比起大多数的指令和MenuItems ,我想还是less了魔法绑定。


可能的专业提示:

整个CommandBinding东西困惑了我一会儿。 我相信这只是针对特定的命令types。 也就是说,你不能连接任何你喜欢的Command 。 像这里吹嘘的东西 (无可否认是一个体面的介绍教程!)…

它可能不是很明显,但通过使用命令,我们得到了一大堆免费的东西:项目上的键盘快捷方式,文本和InputGestureText,WPF根据活动控件及其状态自动启用/禁用项目。 在这种情况下,剪切和复制被禁用,因为没有文本被选中,但粘贴被启用,因为我的剪贴板不是空的!

…有点神奇,并不一定是好的,当你不熟悉WPF菜单的时候会感到困惑。

你也可以在XAML中声明RoutedUICommand

 <Window.Resources> <RoutedUICommand x:Key="BuildCmd" Text="Build"> <RoutedUICommand.InputGestures> <KeyGesture>CTRL+SHIFT+B</KeyGesture> </RoutedUICommand.InputGestures> </RoutedUICommand> </Window.Resources> 

做绑定

 <Window.CommandBindings> <CommandBinding Command="{StaticResource BuildCmd}" Executed="BuildCmdExecuted"/> </Window.CommandBindings> 

并在MenuItem

 <MenuItem Command="{StaticResource BuildCmd}"/> 

这里讨论另一个解决scheme。