定义MenuItem快捷方式

Fel*_*oto 47 wpf keyboard-shortcuts

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

但这不适用于快捷方式,只需点击:

<MenuItem Header="Editar">
    <MenuItem Header="Procurar" Name="MenuProcurar"
              InputGestureText="Ctrl+F"
              Click="MenuProcurar_Click">
        <MenuItem.ToolTip>
            <ToolTip>
                Procurar
            </ToolTip>
        </MenuItem.ToolTip>
    </MenuItem>
</MenuItem>
Run Code Online (Sandbox Code Playgroud)

我正在使用WPF 4.0

H.B*_*.B. 59

您需要在快捷方式应该起作用的控件中使用KeyBindings(CommandBindings如果您(重新)使用,RoutedCommands例如在ApplicationCommands类中找到的那些).

例如

<Window.CommandBindings>
        <CommandBinding Command="New" Executed="CommandBinding_Executed" />
</Window.CommandBindings>
<Window.InputBindings>
        <KeyBinding Key="N" Modifiers="Control" Command="New"/>
</Window.InputBindings>
Run Code Online (Sandbox Code Playgroud)

对于自定义RoutedCommands:

static class CustomCommands
{
    public static RoutedCommand DoStuff = new RoutedCommand();
}
Run Code Online (Sandbox Code Playgroud)

用法:

<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>
Run Code Online (Sandbox Code Playgroud)

(实现ICommand接口而不是使用它通常更方便RoutedCommands.你可以有一个构造函数,它接受代理ExecuteCanExecute轻松创建执行不同操作的命令,这些实现通常被称为DelegateCommandRelayCommand.这种方式你不需要CommandBindings.)

  • 太复杂了,太多的样板. (8认同)
  • 但为什么?OOP不适用于所有事情.这不是万灵药.为什么要让事情比他们需要的更复杂?Windows窗体快捷方式非常棒:单击菜单项>转到属性窗格>选择相应的快捷方式>保存>调试=工作!WPF:ICommand AbstractionLayer RoutedCommands KeyBindings CommandBindings DelegateCommand RelayCommand执行CanExecute ICommand接口OOP血腥了这个以及其他一切DEBUG哦一些不正确的重试. (8认同)
  • 我这样做了 但对于一件简单的事情来说工作太多了.如果不工作,为什么存在InputGestureText? (7认同)
  • 没有人说这很简单; InputGestureText就是这样:Text,它什么都不做.从引用:"此属性不将输入手势与菜单项关联;它只是将文本添加到菜单项.应用程序必须处理用户的输入以执行操作.有关如何将命令与a关联的信息菜单项,请参阅命令." (5认同)
  • 以前在WinForms中很简单; 我猜这就是人们抱怨的原因. (5认同)

Gui*_*ish 58

HB是对的......我只是想增加更多精确度.

删除Click您的事件MenuItem并将其与相关联Command.

1 - 添加/创建命令:

<Window.CommandBindings>
     <CommandBinding Command="Open" Executed="OpenCommandBinding_Executed"/>
     <CommandBinding Command="SaveAs" Executed="SaveAsCommandBinding_Executed"/>
</Window.CommandBindings>
Run Code Online (Sandbox Code Playgroud)

这些命令引用了以下代码:

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
}
Run Code Online (Sandbox Code Playgroud)

2 - 将命令与所需键关联:

<Window.InputBindings>
    <KeyBinding Key="O" Modifiers="Control" Command="Open"/>
    <KeyBinding Key="S" Modifiers="Control" Command="SaveAs"/>
</Window.InputBindings>
Run Code Online (Sandbox Code Playgroud)

3 - 最后用菜单项分配命令(InputGestureText只是一个装饰文本):

<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>
Run Code Online (Sandbox Code Playgroud)

这样,多个输入可以与同一命令相关联.

  • 更多细节:大多数[预定义命令](http://msdn.microsoft.com/en-us/library/ms752308.aspx#Command_Library)包含输入绑定.例如`Open`命令.如果使用这样的命令,则不需要显式指定`KeyBinding`或`InputGestureText`.此外,如果默认文本适合您,您可以省略`Header`. (3认同)
  • 谢谢..这非常简洁,乐于助人.正是我将Menu Click处理程序转换为Command处理程序所需的信息. (2认同)

Ign*_*cia 11

在我看来,在标题中使用_更容易.这将自动创建所需的HotKey.

例如:

<MenuItem Header="_Editar">
<MenuItem Header="_Procurar" Name="MenuProcurar"
          InputGestureText="Ctrl+F"
          Click="MenuProcurar_Click">
    <MenuItem.ToolTip>
        <ToolTip>
            Procurar
        </ToolTip>
    </MenuItem.ToolTip>
</MenuItem>
</MenuItem>
Run Code Online (Sandbox Code Playgroud)

  • 这创造了一个热键,而不是捷径.在没有先浏览菜单的情况下执行类似Ctrl + F的操作来启动"查找"命令非常常见. (13认同)

Eli*_*iko 8

您也可以RoutedUICommand在XAML中声明:

<Window.Resources>
    <RoutedUICommand x:Key="BuildCmd" Text="Build">
        <RoutedUICommand.InputGestures>
            <KeyGesture>CTRL+SHIFT+B</KeyGesture>
        </RoutedUICommand.InputGestures>
    </RoutedUICommand>      
</Window.Resources>
Run Code Online (Sandbox Code Playgroud)

做绑定

<Window.CommandBindings>
    <CommandBinding Command="{StaticResource BuildCmd}" Executed="BuildCmdExecuted"/>
</Window.CommandBindings>
Run Code Online (Sandbox Code Playgroud)

并在 MenuItem

<MenuItem Command="{StaticResource BuildCmd}"/>
Run Code Online (Sandbox Code Playgroud)

这里讨论另一种解决方案.


ruf*_*fin 8

我对Windows.Forms和gulp VB 6 过于偏见,所以我同意JonathanJase的观点,即必须采用更简单/程序化的方法静态连接不一定的事件处理程序CommandBindings.我想,有.

我相信,CommandBinding这篇MSDN博客文章中可以找到使用非处理程序,但强调按钮的好教程.我会提炼并瞄准MenuItems ...

创建ICommand

首先,创建一个实现类ICommand.当然,如果需要,您可以将它放在任何位置,甚至可以放在MainWindow.xaml.cs文件中,以使您的演示代码非常简单.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;
} 
Run Code Online (Sandbox Code Playgroud)

正如本教程有用的指出,您可以从任何地方调用此命令,代码如...

var hwc = new HelloWorldCommand();
if (hwc.CanExecute(this))
    hwc.Execute(this);
Run Code Online (Sandbox Code Playgroud)

在窗口中声明您的命令

所以让HelloWorldCommand我们为我们的Window 添加一种"声明",以便我们以后可以使用它.在Window标签内部,将命令注册为资源:

<Window.Resources>
    <local:HelloWorldCommand x:Key="hwc"/>
</Window.Resources>
Run Code Online (Sandbox Code Playgroud)

现在我们有一个简洁的快捷方式来链接到这个"本地命名空间"命令"hwc",虽然你显然可以使用你想要的任何字符串.我们将在xaml中使用它.

接线(并重复使用!)命令

让我们将MenuItems 添加到我们的xaml中.我已经Grid用a 替换了股票,DockPanel因为这是最简单的方式(对我来说)有等间距的小部件填充Window,尽管我已经离开了我的所有其余UI.

请注意Command="{StaticResource hwc}"每个MenuItem声明中的s .关键是hwc在那里 - 请记住,这是我们HelloWorldCommandWindow关卡中设置的快捷方式.而且,当然,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>
Run Code Online (Sandbox Code Playgroud)

CommandParameters用于区分事件源

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

另请注意,您可以根据需要使这些对象变得复杂.您可以使用MenuItem标记中的属性来定义参数,也可以使用"真实" <MenuItem.CommandParameter>标记(如上面的"打开"菜单项)来定义复杂的内容.在这种情况下,我们传递整个父Window对象,这是将VB6-ish上下文抛出到事件处理程序代码中的最简单(尽管不是最干净)的方法.

MenuItems 添加键盘快捷键(又名"回答OP")

现在我们终于可以回答原来的问题!让我们最后连接Close菜单项的键盘快捷键.你会注意到我们已经宣布了InputGestureText.就其本身而言,InputGestureText只是化妆品.如果我们过于挑剔,我们可以争辩说,创建键盘快捷键的机制与根本没有任何直接的,固有的关系MenuItem!

我们需要代替(或另外)在Window级别注册Ctrl-G的监听器以捕获击键.所以在Window标签的顶层,插入这个(基本上从这里开始):

<Window.InputBindings>
    <KeyBinding Modifiers="Control"
                Key="G"
                Command="{StaticResource hwc}" 
                CommandParameter="window input binding"
    />
</Window.InputBindings>
Run Code Online (Sandbox Code Playgroud)

请注意,您可以通过将CommandParameter标记KeyBinding从自动关闭的XML移动到"真正的"打开和关闭KeyBinding标记来将标记放入您的标记中.

我们已经完成了.运行您的应用程序,然后按Ctrl-G.Whaddup.

非常直截了当,一旦你拥有了球员,并且比大多数前奏命令更少魔术绑定MenuItems,我想.


可能的专业提示:

整件事CommandBinding困扰了我一段时间.这只是针对特定的命令类型,我相信.也就是说,你不能只是连接任何Command你喜欢的.像这里吹嘘的东西(在一些不错的介绍教程!)......

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

...有点神奇,并不一定好,当你是WPF菜单的新手时,可能会让人感到困惑.