How can I toggle the main menu visibility using the Alt key in WPF?
-
10-07-2019 - |
Question
I'd like the main menu in my WPF app to behave like the main menu in IE8:
- it's not visible when the app starts
- pressing and releasing Alt makes it visible
- pressing and releasing Alt again makes it invisible again
- repeat until bored
How can I do this? Does it have to be code?
Added in response to answers submitted, because I'm still having trouble:
My Shell code-behind now looks like this:
public partial class Shell : Window
{
public static readonly DependencyProperty IsMainMenuVisibleProperty;
static Shell()
{
FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();
metadata.DefaultValue = false;
IsMainMenuVisibleProperty = DependencyProperty.Register(
"IsMainMenuVisible", typeof(bool), typeof(Shell), metadata);
}
public Shell()
{
InitializeComponent();
this.PreviewKeyUp += new KeyEventHandler(Shell_PreviewKeyUp);
}
void Shell_PreviewKeyUp(object sender, KeyEventArgs e)
{
if (e.SystemKey == Key.LeftAlt || e.SystemKey == Key.RightAlt)
{
if (IsMainMenuVisible == true)
IsMainMenuVisible = false;
else
IsMainMenuVisible = true;
}
}
public bool IsMainMenuVisible
{
get { return (bool)GetValue(IsMainMenuVisibleProperty); }
set { SetValue(IsMainMenuVisibleProperty, value); }
}
}
Solution
You can use the PreviewKeyDown
event on the window. To detect the Alt key you will need to check the SystemKey
property of the KeyEventArgs
, as opposed to the Key property which you normally use for most other keys.
You can use this event to set a bool
value which has been declared as a DependencyProperty
in the windows code behind.
The menu's Visibility
property can then be bound to this property using the BooleanToVisibilityConverter
.
<Menu
Visibility={Binding Path=IsMenuVisibile,
RelativeSource={RelativeSource AncestorType=Window},
Converter={StaticResource BooleanToVisibilityConverter}}
/>
OTHER TIPS
I'd try looking into handling the PreviewKeyDown
event on your window. I'm not sure if pressing Alt triggers this event or not, but if it does, then I'd toggle a bool
which is bound to the visibility of the main menu of the window.
If PreviewKeyDown
doesn't work, I'm not sure what else to try. You could look into getting at the actual Windows messages sent to your window, but that could get messy very quickly.
It would be better to use GetKeyboardState
with VK_MENU
to handle both left and right Alt, to mimic the behavior of IE / Windows Explorer (Vista+) you'll need to track the previously focused element to store focus, on a VK_MENU
press whilst the focused element is within your main menu. You also want to be doing this work on PreviewKeyUp
(not down).
I just came across this problem myself. I tried hooking into the PreviewKeyDown
event, but found it to be unreliable. Instead I found the InputManager
class where you can hook into the EnterMenuMode
from managed code. The manager exposes two events, for enter and exit. The trick is to not collapse the menu, but set it's container height to zero when it is to be hidden. To show it, simply clear the local value and it will take its previous height.
From my TopMenu
user control:
public TopMenu()
{
InitializeComponent();
InputManager.Current.EnterMenuMode += OnEnterMenuMode;
InputManager.Current.LeaveMenuMode += OnLeaveMenuMode;
Height = 0;
}
private void OnLeaveMenuMode(object sender, System.EventArgs e)
{
Height = 0;
}
private void OnEnterMenuMode(object sender, System.EventArgs e)
{
ClearValue(HeightProperty);
}