简体   繁体   English

WPF 在键盘导航模式下显示菜单

[英]WPF Show Menu in Keyboard Navigation Mode

Backstory aka My Configuration背景故事又名我的配置

Like many, I have an application which has a Menu docked to the top.像许多人一样,我有一个应用程序,它有一个停靠在顶部的菜单。 I wanted this menu to be hidden until I pressed the alt key, where I'd then be able to navigate this menu either using my keyboard or by clicking my way through the MenuItems.我希望在按下alt键之前隐藏此菜单,然后我可以使用键盘或通过单击菜单项来导航此菜单。

In my ViewModel, I made a boolean property called ShowMenu , an ICommand called ShowMenuCommand which operates as a flip flop for ShowMenu , and proceeded to wire things up with data binding.在我的ViewModel,我做了一个叫布尔属性ShowMenu ,一个ICommand所谓ShowMenuCommand操作为一个触发器ShowMenu ,并着手线的事情了数据绑定。 You can see that here:你可以在这里看到:

ShowMenuCommand = new RelayCommand(
    _ => ShowMenu = !ShowMenu);

The Menu is set up as such:菜单设置如下:

<Menu Name="MainMenu" DockPanel.Dock="Top"
    Visibility="{Binding ShowMenu, Converter={StaticResource BoolToVis}}"
    LostFocus="MainMenu_OnLostFocus">

I also configured keybindings for left and right alt that fire the ShowMenuCommand .我还为触发ShowMenuCommand左右 alt 配置了键绑定。

<Window.InputBindings>
    <KeyBinding Key="F1" Command="{Binding AboutCommand}" />
    <KeyBinding Key="LeftAlt" Modifiers="Alt" Command="{Binding ShowMenuCommand}" />
    <KeyBinding Key="RightAlt" Modifiers="Alt" Command="{Binding ShowMenuCommand}" />
</Window.InputBindings>

This works exactly as I configured it to work: The menu is normally hidden, but when I press alt it appears and allows me to navigate the menu items until I click away or I select an item and it loses focus, the LostFocus handler setting ShowMenu to false.这完全按照我的配置工作:菜单通常是隐藏的,但是当我按下alt它会出现并允许我导航菜单项,直到我单击离开或我选择一个项目并且它失去焦点, LostFocus处理程序设置ShowMenu为假。

The Problem问题

Having done this, I seem to have lost the ability to enter Keyboard Navigation Mode.这样做后,我似乎失去了进入键盘导航模式的能力。 For those who don't know what I mean, normally when you press alt in a gui app, certain characters become underlined, and you can press those characters on your keyboard to navigate the UI.对于那些不知道我的意思的人,通常当您在 gui 应用程序中按alt时,某些字符会变成下划线,您可以按键盘上的这些字符来导航 UI。 I don't know the formal name for this, so bonus points to anyone who can provide the actual name.我不知道它的正式名称,因此任何可以提供实际名称的人都会获得奖励积分。

Sources for getting this far达到此目的的来源

How to make WPF menu bar visible when ALT-key is pressed 按下ALT键时如何使WPF菜单栏可见

LeftAlt Keybinding in WPF WPF 中的 LeftAlt 键绑定

What Now?现在怎么办?

I've been searching high and low, crawling through keyboard classes and UIElement in hopes of finding something to fix this, and I've come up with a couple possible solutions.我一直在搜索高低,通过键盘类和UIElement爬行,希望能找到解决这个问题的方法,我想出了几个可能的解决方案。 That said, the reason I have resorted to StackOverflow is because I don't know how to pose my google search in such a way that I find what I'm looking for.也就是说,我求助于 StackOverflow 的原因是因为我不知道如何以这样一种方式来定位我的谷歌搜索,以便我找到我正在寻找的东西。

My proposed solutions are as follows:我提出的解决方案如下:

  1. Modify ShowMenuCommand to toggle keyboard navigation mode in addition to modifying visibility.除了修改可见性之外,还修改ShowMenuCommand以切换键盘导航模式。
  2. Remove my keybindings and wire the menu's visibility to whether keyboard navigation mode is enabled.删除我的键绑定并将菜单的可见性连接到是否启用了键盘导航模式。
    • I thought I would've had this with UIElement#IsInputMethodEnabled , however this does not appear to be the case.我以为我会在UIElement#IsInputMethodEnabled ,但情况似乎并非如此。 That said, I don't know if it matters what element you select, and I don't remember if I tried targeting the Menu or the Window.也就是说,我不知道你选择什么元素是否重要,我不记得我是否尝试过定位菜单或窗口。

If anyone else has any third idea or might know something I'm missing, please do let me know.如果其他人有任何第三个想法或可能知道我遗漏的东西,请告诉我。 Hiding the menu bar until you unhide it with alt should be something terribly trivial to set up, so I'd not be surprised if I'm missing something.隐藏菜单栏直到你用alt取消隐藏它应该是非常简单的设置,所以如果我遗漏了什么我不会感到惊讶。

Additional Context附加上下文

If you would like to see any code surrounding the provided snippets, you can view the project source code on GitHub.如果您想查看围绕所提供代码段的任何代码,可以在 GitHub 上查看项目源代码

So after some additional research and a some help from @Vlad, the final solution is the following:因此,经过一些额外的研究和@Vlad 的帮助,最终的解决方案如下:

  1. Menu visibility is bound to ShowMenu property in View Controller.菜单可见性绑定到视图控制器中的ShowMenu属性。
  2. Window has KeyUp event handler which watches for the alt key. Window 有 KeyUp 事件处理程序,它监视 alt 键。
private void MainWindow_OnKeyUp(object sender, KeyEventArgs e)
{
    if (e.Key == Key.System && (e.SystemKey == Key.LeftAlt || e.SystemKey == Key.RightAlt))
    {
        MainWindowViewModel mwvm = (MainWindowViewModel)DataContext;

        mwvm.ShowMenu = !mwvm.ShowMenu;
    }
}

This works, except the menu will remain visible after an item is selected.这是有效的,除了在选择项目后菜单将保持可见。 I tried creating an item template to take care of it all at once, but it didn't want to fire.我尝试创建一个项目模板来一次性完成所有工作,但它不想触发。

  1. Handle Click event on relevant menu items, skipping those that are just categories.处理相关菜单项上的 Click 事件,跳过那些只是类别的事件。

The only thing this doesn't take care of is when the user clicks away from the menu.唯一没有注意的是当用户点击菜单时。 I tried attaching a LostFocus event to the Menu, however this event fires when the menu opens, perhaps because the focus is being taken away from the Menu itself and onto the ContextMenu provider or whatever actually handles drawing the open menu.我尝试将 LostFocus 事件附加到菜单,但是当菜单打开时会触发此事件,这可能是因为焦点从菜单本身转移到 ContextMenu 提供程序或实际处理绘制打开菜单的任何内容上。

I'll need to do some more research and some code cleanup, but the above solution works relatively okay.我需要做更多的研究和一些代码清理,但上述解决方案的工作相对还好。

Edit: I'll leave this answer unselected for a couple days just in case anyone else has any other ideas.编辑:我会在几天内不选择这个答案,以防其他人有任何其他想法。

Edit 2: I found a solution for my use.编辑 2:我找到了一个供我使用的解决方案。 Since I only have one top-level menu item on this menu, I hooked the MenuItem's SubmenuClosed event.因为我在这个菜单上只有一个顶级菜单项,所以我挂钩了 MenuItem 的SubmenuClosed事件。 When this happens (either because of a user selecting an option or them clicking away), it hides the menu by setting ShowMenu to false.当发生这种情况时(因为用户选择了一个选项或他们点击离开),它会通过将ShowMenu设置为 false 来隐藏菜单。

It's probably not the most elegant solution, but it's functional.这可能不是最优雅的解决方案,但它很实用。 I'll look into cleaning it up later.稍后我会考虑清理它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM