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

时间:2019-04-20 16:46:57

标签: c# .net wpf data-binding

背景故事或我的配置

与许多人一样,我有一个应用程序,其中一个菜单停靠在顶部。我希望一直隐藏此菜单,直到按一下alt键,然后才可以使用键盘或单击MenuItems的方式在此菜单中导航。

在我的ViewModel中,我创建了一个名为ShowMenu的布尔属性,一个名为ICommand的{​​{1}},该布尔属性用作ShowMenuCommand的触发器,然后继续进行连接与数据绑定。您可以在这里看到它:

ShowMenu

菜单设置如下:

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

我还为触发<Menu Name="MainMenu" DockPanel.Dock="Top" Visibility="{Binding ShowMenu, Converter={StaticResource BoolToVis}}" LostFocus="MainMenu_OnLostFocus"> 的左右alt配置了键绑定。

ShowMenuCommand

这完全符合我配置的工作方式:菜单通常处于隐藏状态,但是当我按<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> 时,它会出现,并允许我浏览菜单项,直到我单击离开或选择一个项而丢失焦点,alt处理程序将LostFocus设置为false。

问题

完成此操作后,我似乎失去了进入键盘导航模式的能力。对于那些不了解我的意思的人,通常当您在gui应用程序中按ShowMenu时,某些字符会带有下划线,并且您可以在键盘上按这些字符来导航UI。我不知道它的正式名称,所以奖励指向任何可以提供实际名称的人。

实现这一目标的资源

How to make WPF menu bar visible when ALT-key is pressed

LeftAlt Keybinding in WPF

现在做什么?

我一直在搜寻高低,在键盘类和alt中进行爬网,希望找到可以解决此问题的方法,并且提出了一些可能的解决方案。就是说,我求助于StackOverflow的原因是因为我不知道如何以我能找到所需内容的方式构成Google搜索。

我提出的解决方案如下:

  1. 修改UIElement除了切换可见性,还可以切换键盘导航模式。
  2. 删除我的按键绑定,并将菜单的可见性连接到是否启用了键盘导航模式。
    • 我以为我会在ShowMenuCommand中遇到这个问题,但是事实并非如此。就是说,我不知道您选择的 元素是否重要,我也不记得是否尝试定位菜单或窗口。

如果其他人有任何第三个想法,或者可能知道我所缺少的内容,请告诉我。隐藏菜单栏,直到用UIElement#IsInputMethodEnabled取消隐藏为止,这应该是一件非常琐碎的事情,因此,如果我错过了某些东西,我不会感到惊讶。

其他上下文

如果您希望查看提供的代码片段周围的任何代码,则可以在GitHub上查看project source code

1 个答案:

答案 0 :(得分:1)

因此,经过一些额外的研究和@Vlad的帮助,最终的解决方案如下:

  1. 菜单可见性已绑定到View Controller中的ShowMenu属性。
  2. 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;
    }
}

这有效,除了在选择一个项目后菜单仍然可见之外。我尝试创建一个项目模板来一次完成所有工作,但是它不想触发。

  1. 处理相关菜单项上的Click事件,跳过那些只是类别。

唯一不需要处理的是用户单击菜单以外的地方。我尝试将LostFocus事件附加到Menu,但是在菜单打开时会触发此事件,这可能是因为焦点从Menu本身移到了ContextMenu提供程序上,或者实际上是在处理打开菜单的任何操作。

我需要做更多的研究和一些代码清除,但是上述解决方案相对可以。

编辑:几天之内,我将不选择此答案,以防万一其他人有其他想法。

编辑2:我找到了可以使用的解决方案。由于此菜单上只有一个顶级菜单项,因此我钩住了MenuItem的SubmenuClosed事件。发生这种情况时(由于用户选择了一个选项或他们单击了鼠标),它会通过将ShowMenu设置为false来隐藏菜单。

这可能不是最优雅的解决方案,但它是实用的。我待会儿会清理它。