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.
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. 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
.
<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.
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. 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
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. 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.
My proposed solutions are as follows:
ShowMenuCommand
to toggle keyboard navigation mode in addition to modifying visibility.UIElement#IsInputMethodEnabled
, however this does not appear to be the case. 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.
Additional Context
If you would like to see any code surrounding the provided snippets, you can view the project source code on GitHub.
So after some additional research and a some help from @Vlad, the final solution is the following:
ShowMenu
property in View Controller.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.
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.
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. Since I only have one top-level menu item on this menu, I hooked the MenuItem's SubmenuClosed
event. When this happens (either because of a user selecting an option or them clicking away), it hides the menu by setting ShowMenu
to false.
It's probably not the most elegant solution, but it's functional. I'll look into cleaning it up later.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.