为什么设置 MenuItem.InputGestureText 不会导致当我执行输入手势时激活 MenuItem?

发布于 2024-10-23 12:27:55 字数 427 浏览 1 评论 0原文

我想为 MenuItem 实现键盘快捷键。我使用了下面的代码:

<MenuItem Header="_New" InputGestureText="CTRL+N" Click="NewMenu_Click">
    <MenuItem.Icon>
        <Image Source= "Images\NEW.PNG" Width="25" Height="28" />
    </MenuItem.Icon>
</MenuItem>`

但是当我按下 CTRL+N 时,InputGestureText 属性没有响应。我正在使用 Visual Studio Express Edition 2010。我在这里遗漏了什么吗?

I want to implement Keyboard shortcuts for a MenuItem. I have used the code below:

<MenuItem Header="_New" InputGestureText="CTRL+N" Click="NewMenu_Click">
    <MenuItem.Icon>
        <Image Source= "Images\NEW.PNG" Width="25" Height="28" />
    </MenuItem.Icon>
</MenuItem>`

But the InputGestureText property is not responding when I pressed the CTRL+N. I am using Visual Studio Express Edition 2010. Am I missing anything here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

比忠 2024-10-30 12:27:55

该属性的文档中非常明确:

此属性不关联
使用菜单项输入手势;它
只需将文本添加到菜单项即可。这
应用程序必须处理用户的
输入以执行操作。为了
有关如何关联的信息
带有菜单项的命令,请参阅
命令

It is quite explicit in the documentation for the property:

This property does not associate the
input gesture with the menu item; it
simply adds text to the menu item. The
application must handle the user's
input to carry out the action. For
information on how to associate a
command with a menu item, see
Command.

不知在何时 2024-10-30 12:27:55

执行此操作的最佳方法是创建一个 Command,并将 InputGesture 与该命令相关联:

public static class Commands
{
    public static readonly RoutedCommand CreateNew = new RoutedCommand("New", typeof(Commands));

    static Commands()
    {
        SomeCommand.InputGestures.Add(new KeyGesture(Key.N, ModifierKeys.Control));
    }
}

...

// Wherever you want to create the MenuItem. "local" should be the namespace that
// you delcared "Commands" in.
<MenuItem Header="_New" Command="{x:Static local:Commands.CreateNew}">

...

// Wherever you want to process the command. I am assuming you want to do it in your 
// main window, but you can do it anywhere in the route between your main window and 
// the menu item.
<Window.CommandBindings>
    <CommandBinding Command="{x:Static local:Commands.CreateNew}"> Executed="CreateNew_Executed" />
</Window.CommandBindings>

...

// In the code behind for your main window (or whichever file you put the above XAML in)
private void CreateNew(object sender, ExecutedRoutedEventArgs e)
{
    ...
}

如果您确实只想要一个“新建”命令,则可以跳过创建RoatedCommandInputGesture,因为该命令已为您创建:

<MenuItem Header="_New" Command="New">

...

<Window.CommandBindings>
    <CommandBinding Command="New" Executed="New_Executed" />
</Window.CommandBindings>

...

private void New_Executed(object sender, ExecutedRoutedEventArgs e)
{
    ...
}

The best way to do this is to make a Command, and associate the InputGesture with that command:

public static class Commands
{
    public static readonly RoutedCommand CreateNew = new RoutedCommand("New", typeof(Commands));

    static Commands()
    {
        SomeCommand.InputGestures.Add(new KeyGesture(Key.N, ModifierKeys.Control));
    }
}

...

// Wherever you want to create the MenuItem. "local" should be the namespace that
// you delcared "Commands" in.
<MenuItem Header="_New" Command="{x:Static local:Commands.CreateNew}">

...

// Wherever you want to process the command. I am assuming you want to do it in your 
// main window, but you can do it anywhere in the route between your main window and 
// the menu item.
<Window.CommandBindings>
    <CommandBinding Command="{x:Static local:Commands.CreateNew}"> Executed="CreateNew_Executed" />
</Window.CommandBindings>

...

// In the code behind for your main window (or whichever file you put the above XAML in)
private void CreateNew(object sender, ExecutedRoutedEventArgs e)
{
    ...
}

If you really just want a "New" command, you can skip creating the RoutedCommand and InputGesture, because that command is already created for you:

<MenuItem Header="_New" Command="New">

...

<Window.CommandBindings>
    <CommandBinding Command="New" Executed="New_Executed" />
</Window.CommandBindings>

...

private void New_Executed(object sender, ExecutedRoutedEventArgs e)
{
    ...
}
后知后觉 2024-10-30 12:27:55

一种不涉及命令和绑定的解决方案是重写所属窗口的 OnKeyDown 方法,并搜索具有与键盘事件匹配的 KeyGesture 的菜单项。

下面是 Window 的 OnKeyDown 覆盖的代码:

protected override void OnKeyDown(KeyEventArgs e)
{
    base.OnKeyDown(e);

    // here I suppose the window's menu is named "MainMenu"
    MainMenu.RaiseMenuItemClickOnKeyGesture(e);
}

下面是将菜单项与键盘事件相匹配的实用程序代码:

    public static void RaiseMenuItemClickOnKeyGesture(this ItemsControl control, KeyEventArgs args) => RaiseMenuItemClickOnKeyGesture(control, args, true);
    public static void RaiseMenuItemClickOnKeyGesture(this ItemsControl control, KeyEventArgs args, bool throwOnError)
    {
        if (args == null)
            throw new ArgumentNullException(nameof(args));

        if (control == null)
            return;

        var kgc = new KeyGestureConverter();
        foreach (var item in control.Items.OfType<MenuItem>())
        {
            if (!string.IsNullOrWhiteSpace(item.InputGestureText))
            {
                KeyGesture gesture = null;
                if (throwOnError)
                {
                    gesture = kgc.ConvertFrom(item.InputGestureText) as KeyGesture;
                }
                else
                {
                    try
                    {
                        gesture = kgc.ConvertFrom(item.InputGestureText) as KeyGesture;
                    }
                    catch
                    {
                    }
                }

                if (gesture != null && gesture.Matches(null, args))
                {
                    item.RaiseEvent(new RoutedEventArgs(MenuItem.ClickEvent));
                    args.Handled = true;
                    return;
                }
            }

            RaiseMenuItemClickOnKeyGesture(item, args, throwOnError);
            if (args.Handled)
                return;
        }
    }

One solution that doesn't involve commands and bindings is to override the owning Window's OnKeyDown method and search a menu item that has a KeyGesture that matches the keyboard event.

Here is the code for the Window's OnKeyDown override:

protected override void OnKeyDown(KeyEventArgs e)
{
    base.OnKeyDown(e);

    // here I suppose the window's menu is named "MainMenu"
    MainMenu.RaiseMenuItemClickOnKeyGesture(e);
}

And here is the utility code that matches a menu item with the keyboard event:

    public static void RaiseMenuItemClickOnKeyGesture(this ItemsControl control, KeyEventArgs args) => RaiseMenuItemClickOnKeyGesture(control, args, true);
    public static void RaiseMenuItemClickOnKeyGesture(this ItemsControl control, KeyEventArgs args, bool throwOnError)
    {
        if (args == null)
            throw new ArgumentNullException(nameof(args));

        if (control == null)
            return;

        var kgc = new KeyGestureConverter();
        foreach (var item in control.Items.OfType<MenuItem>())
        {
            if (!string.IsNullOrWhiteSpace(item.InputGestureText))
            {
                KeyGesture gesture = null;
                if (throwOnError)
                {
                    gesture = kgc.ConvertFrom(item.InputGestureText) as KeyGesture;
                }
                else
                {
                    try
                    {
                        gesture = kgc.ConvertFrom(item.InputGestureText) as KeyGesture;
                    }
                    catch
                    {
                    }
                }

                if (gesture != null && gesture.Matches(null, args))
                {
                    item.RaiseEvent(new RoutedEventArgs(MenuItem.ClickEvent));
                    args.Handled = true;
                    return;
                }
            }

            RaiseMenuItemClickOnKeyGesture(item, args, throwOnError);
            if (args.Handled)
                return;
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文