定义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
如果您(重新)使用RoutedCommands
如ApplicationCommands
类中的那些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
可以有一个构造方法,这个构造方法需要委托Execute
和CanExecute
来轻松创build执行不同事情的命令,这种实现通常被称为DelegateCommand
或RelayCommand
。不需要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。 我已经用DockPanel
replace了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
菜单项的键盘快捷键。 你会注意到我们已经声明了一个InputGestureText
。 InputGestureText
本身只是一个整体 。 如果我们过于挑剔,我们可以争辩说创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。