Another WPF Set focus problem with Button Click (control not a child at design time) - wpf

I have a button on a WPF window that adds a tabitem to a tabcontrol on the window. A user control that fills that tabitem is also created in that event. I want to set the focus to a textbox on that user control. I've tried all kinds of txt.Focus code and so forth but the button always still have focus after the click event is executed.
I can't use this as the textbox is not part of the xaml on this window at design time.
MyAttachedProps:EventFocusAttachment.ElementToFocus="{Binding ElementName=NotAvailableAtDesignTime}"
The only thing I can think of is a timer to execute after the button click but there has to be a better way.

You could use a bool attached dependency property.
Bind this to a public bool property in your viewmodel.
Set that to true when you want to focus the control.
I have a bit of code. Can't recall if I wrote it or grabbed it off the web. And I can't recall actually using it either.
public static class FocusExtension
{
public static bool GetIsFocused(DependencyObject obj)
{
return (bool)obj.GetValue(IsFocusedProperty);
}
public static void SetIsFocused(DependencyObject obj, bool value)
{
obj.SetValue(IsFocusedProperty, value);
}
public static readonly DependencyProperty IsFocusedProperty =
DependencyProperty.RegisterAttached(
"IsFocused", typeof(bool), typeof(FocusExtension),
new UIPropertyMetadata(false, OnIsFocusedPropertyChanged));
private static async void OnIsFocusedPropertyChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var uie = (UIElement)d;
if ((bool)e.NewValue)
{
await Task.Delay(200);
uie.Focus();
Keyboard.Focus(uie);
}
}
}
This the await task delay introduces a 200ms wait so other stuff can finish whatever it's doing. You could instead defer the focussing using dispatcher.
Application.Current.Dispatcher.InvokeAsync(new Action(() =>
{
uie.Focus();
Keyboard.Focus(uie);
}), DispatcherPriority.ContextIdle);
Due to closures, that code will capture whatever uie is so long as it's in scope.

Related

Why does PropertyChangedCallback method not execute from Dependency Property OverrideMetadata?

I have a class called CustomGrid which derives from the Grid class. I am attempting to run a method when there are changes made to the grid's parent window's title by using OverrideMetadata on the Window class's TitleProperty. My approach to this problem, however, does not seem to work despite having another PropertyChangedCallback method I implemented, that works, using the same approach (OverrideMetadata) for the grid's MarginProperty:
public class CustomGrid : Grid
{
static CustomGrid()
{
Type ownerType = typeof(CustomGrid);
MarginProperty.OverrideMetadata(ownerType, new FrameworkPropertyMetadata(new PropertyChangedCallback(OnMarginPropertyChanged)));
Window.TitleProperty.OverrideMetadata(ownerType, new FrameworkPropertyMetadata(new PropertyChangedCallback(OnTitlePropertyChanged)));
}
private static void OnMarginPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// This executes when the grid's margin changes.
}
private static void OnTitlePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// This does not execute when the parent window's title changes.
}
}
Why does the OnTitlePropertyChanged method not execute when the grid's parent window's title is changed? Thanks.
The callback method is not called because you did not set the Window.Title property on a CustomGrid instance.
The expression
Window.TitleProperty.OverrideMetadata(
typeof(CustomGrid),
new FrameworkPropertyMetadata(OnTitlePropertyChanged));
registers the OnTitlePropertyChanged callback for the type CustomGrid. This means the callback is called whenever the dependency property is set on instances of CustomGrid, but only on those instances, not any objects like e.g. the MainWindow.

How to find the ICommand binding target (the control)

We use the MVVM pattern. In the View, I have binding the save command to a button:
In the view model, I would like to find out the save command binding target, does it possible?
private Button GetBindingControl(ICommand command)
{
// What should I do here:
return button;
}
It's not possible, and it defeats the purpose of MVVM (having the UI logic in the VM regardless of the controls used)
Maybe you could ask instead what problem you are trying to solve.
As #Diego said, this defats the purpose of MVVM because we must try hard not to include visuals or controls in the view models in MVVM...
Having said that there are two options...
Using RoutedCommands
Using Attached Behaviors.
RoutedCommands are not readily allowed in MVVM as they need to be closely command bound to the UI element i.e. in our case the Button. Hence they too defeat the purpose of MVVM.
But MVVM happily co-exists with the Attached Behaviors.
Many developers shy away from this immensely powerful feature. And we can use it along with RoutedCommands.
In your case
Attach to the Button, with a Action delegate.
Attach the string object as command parameter.
Inside the behavior, set the Button.Command with some Routed command.
In the executed event handler, get the button action delegate from the sender / originalsource / source as the button and then call your Action<> accordingly by using e.Parameter string value.
Sample code below...
Assume you have common button utilities of signature Action<Button, string>
public static class ButtonActionUtilities
{
public static Action<Button, string> ButtonActionDelegate
{
get
{
return ExecuteButtonClick;
}
}
public static void ExecuteButtonClick(Button btn, string param)
{
MessageBox.Show(
"You clicked button " + btn.Content + " with parameter " + param);
}
}
Then the attched behavior is as below...
public static class ButtonAttachedBehavior
{
public static readonly DependencyProperty ActionDelegateProperty
= DependencyProperty.RegisterAttached(
"ActionDelegate",
typeof(Action<Button, string>),
typeof(ButtonAttachedBehavior),
new PropertyMetadata(null, OnActionDelegatePropertyChanged));
public static Action<Button, string> GetActionDelegate(
DependencyObject depObj)
{
return (Action<Button, string>)depObj.GetValue(
ActionDelegateProperty);
}
public static void SetActionDelegate(
DependencyObject depObj, Action<Button, string> value)
{
depObj.SetValue(ActionDelegateProperty, value);
}
private static void OnActionDelegatePropertyChanged(
DependencyObject depObj,
DependencyPropertyChangedEventArgs e)
{
if (depObj is Button
&& e.NewValue is Action<Button, string>)
{
((Button)depObj).Command
= new RoutedCommand(
"ActionRoutedCommand",
typeof(ButtonAttachedBehavior));
((Button) depObj).CommandBindings.Add(
new CommandBinding(
((Button) depObj).Command,
OnActionRoutedCommandExecuted));
}
}
private static void OnActionRoutedCommandExecuted(
object sender, ExecutedRoutedEventArgs e)
{
var actionDelegate = GetActionDelegate((Button)e.Source);
actionDelegate((Button) e.Source, (string)e.Parameter);
}
}
And on XAML it will look like this....
<StackPanel>
<Button x:Name="TestButton" Content="Test Me"
local:ButtonAttachedBehavior.ActionDelegate
="{x:Static local:ButtonActionUtilities.ButtonActionDelegate}"
CommandParameter
="{Binding Text, ElementName=ParameterTextBox}"/>
<TextBox x:Name="ParameterTextBox"/>
</StackPanel>
So with the code above you will need to just set the ActionDelegate attached property to approapriate delegate and it will execute that.
I would still suggest you to revamp your existing code setup to separate button specific behaviors to make it more MVVM friendly.

Silverlight Required TextBox Attached Property

I have a need to create an attached property for a TextBox, that enforces a rule that content is required.
NOTE: Unfortunately I am not able to use data annotations, or SL4 validation frameworks.
The textboxes are displayed within the context of a View. The View is reused in many places. When tabbing / clicking between TextBoxes within the view I want a popup message to notify the user if they have left a 'Required' TextBox empty.
Now, I have this working via the LostFocus event:
public static readonly DependencyProperty RequiredProperty =
DependencyProperty.RegisterAttached("Required", typeof(bool), typeof(TextBoxRequiredService),
new PropertyMetadata(OnRequiredChanged));
public static bool GetRequired(DependencyObject d)
{
return (bool)d.GetValue(RequiredProperty);
}
public static void SetRequired(DependencyObject d, bool value)
{
d.SetValue(RequiredProperty, value);
}
private static void OnRequiredChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TextBox textBox = d as TextBox;
textBox.LostFocus += (s, args) => {
if (textBox.Text.Length == 0) {
MessageBox.Show("Required Field!");
textBox.Focus();
}
};
}
But this is getting triggered, obvioulsy, on every lost focus, and there are certain situations, for example closing the view, that i don't want the validation to execute.
So, does anyone have any good suggestions (or examples) on a way to get a Required Text Box service working within a definable scope of actions? Or perhaps some clever alternatives to LostFocus that I could use?
Thanks,
Mark

Adding programatically a command to a listbox in WPF

In my WPF application there is a listbox with items. The listbox is populated via a xmldataprovider from XAML and then binding it to Itemssource property of the listbox.
Well, from XAML, I bind a comand to the listbox by doing:
<ListBox.CommandBindings>
<CommandBinding
Command="{x:Static local:mainApp.MyCmd}"
CanExecute="CanExecute"
Executed ="Executed" />
</ListBox.CommandBindings>
but I don't know how to programatically bind a command to each listboxitem. How to do it?
Thanks in advance.
First sorry by not posting it as a comment. I can't put all this in a comment.
Ok, yes I am not using the Executed and CanExecute properties of the ICommandSource despite I have registered and implemented them in custom class (in xaml they are commented too). I have specified them in routedCommand but not in custom class, I have done it in the constructor of the window by doing this:
WinMain code behind:
public WinMain()
{
InitializeComponent();
// Command binding. If I don't do this Executed and CanExecute are not executed
CommandBindings.Add(new CommandBinding(rcmd,
CommandBinding_Executed, CommandBinding_CanExecute));
}
and then I implement these methods in WinMain code behind too as it:
// ExecutedRoutedEventHandler
private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
// Do stuff
}
// CanExecuteRoutedEventHandler
private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
// cBgWorkers is a class that check if a background worker is running
e.CanExecute = !cBgWorkers.isRunning;
//if (LayoutListBox != null) LayoutListBox.IsEnabled = !cBgWorkers.isRunning;
}
and In WinMain XAML I invoke the command like this:
<Classes:CommandListBox x:Name="LayoutListBox"
Command="{x:Static local:WinMain.rcmd}"
... >
<...>
</Classes:CommandListBox>
And in my custom class CommandListBox I have a CanExecuteChanged in which you can see I enabled or disabled the control depending on whether the background worker is finished or not:
private void CanExecuteChanged(object sender, EventArgs e)
{
this.Enabled = !cBgWorkers.isRunning;
}
but in custom class I haven't implement the event handler you say, OnSelected.
WIthout implementing it all goes ok, the custom control invoke command, and CanExecute method is reached, and CanExecute gets correct value, true or false depending on background worker is finished or not, and the CanExecuteChanged in custom control is raised when CanExecute changes its value. When background worker starts it gets disabled but when it finished it doesn't get enabled. I have debugged, and when background worker finishes I can see CanExecuteChanged is executed and this.Enabled is getting correct value (true) but for some reason in the UI the control continues disabled despite it gets its correct value and despite in RunWOrkerCompleted (in background worker) I force to update UI with CommandManager.InvalidateRequerySuggested().
I solve this by uncomment line:
if (LayoutListBox != null) LayoutListBox.IsEnabled = !cBgWorkers.isRunning;
in CanExecute method. I don't understand what happens.
Then If I do what you say It is not necessary to do it:
CommandBindings.Add(new CommandBinding(rcmd,
CommandBinding_Executed, CommandBinding_CanExecute));
and CommandBinding_Executed & CommandBinding_CanExecute implementations. Am I right?
but if I remove these methods where can I set this.enabled = !cBgWorkers.isRunning ?
I would like WPF to set automatically isEnabled property for my custom control. How to do this?
Thanks in advance.
I am applying the article you say about attached behaviors with a few changes to adapt it to my ListBox. It doesn't work well or perhaps I am doing something wrong. What I want is avoid that ListBox members (listBoxItems) can be select when a long task (background worker) is running. So one of the method of the article that I have modified is:
static void OnListBoxItemSelected(object sender, RoutedEventArgs e)
{
// Only react to the Selected event raised by the ListBoxItem
// whose IsSelected property was modified. Ignore all ancestors
// who are merely reporting that a descendant's Selected fired.
if (!Object.ReferenceEquals(sender, e.OriginalSource))
return;
ListBoxItem item = e.OriginalSource as ListBoxItem;
if (item != null)
{
// (*) See comment under
item.IsEnabled = !cBgWorkers.isRunning;
if (!cBgWorkers.isRunning)
{
item.BringIntoView();
}
}
}
(*) cBgWorkers is a public static Class that has some methods and properties.
One of the properties is isRunning that indicates no background workers is currently running. Then If no background workers is running, listbox members have to be enabled otherwise they have to be disabled so when user clicks over one listbox item the current page don't change to another one because I disabled it before (each listBox items has attached one page in my main application).
When one of the background workers (bw) or all are running and I select listbox item all is ok: listbox item is disabled because there are bw running and it avoid tho change the current page to another one. Of course, If I disabled the listbox item (or listbox items) I can't select it again because it is disabled and that is my problem, because I want that when bw finish the listbox items that have been disabled while bw were running, they get enabled again. Unfortunately with attached behavior as I see it isn't done by WPF automatically and commands have this advantage (controls update automatically by WPF). so, how to disabled/re-enabled listbox items when bw is running or not respectively?
As far as I know and see, one advantage of attached behaviors is that I think it is more efficient because they are not invoking actions constantly (only when the action, for example, selection, is produced). Commands are constantly (not often) checking if actions binded to controls can be executed (so If they can be executed, WPF automatically enables controls otherwise they appear disabled), right?
Thanks.
you could try creating a custom control that derives from ListBoxItem and implementing the ICommandSource interface. I can't think of a more simple solution as of now.
I have done your solution. I have done a custom user control deriving from listbox and implementing ISourceCommand as you said and it works now!!!! ;)
My custom class:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Input;
namespace GParts.Classes
{
public class CommandListBox : ListBox, ICommandSource
{
public CommandListBox() : base()
{
}
// ICommand Interface Members
// Make Command a dependency property so it can use databinding.
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register(
"Command",
typeof(ICommand),
typeof(CommandListBox),
new PropertyMetadata((ICommand)null,
new PropertyChangedCallback(CommandChanged)));
public ICommand Command
{
get
{
return (ICommand)GetValue(CommandProperty);
}
set
{
SetValue(CommandProperty, value);
}
}
// Make Command a dependency property so it can use databinding.
public static readonly DependencyProperty ExecutedProperty =
DependencyProperty.Register(
"Executed",
typeof(object),
typeof(CommandListBox),
new PropertyMetadata((object)null));
public object Executed
{
get
{
return (object)GetValue(ExecutedProperty);
}
set
{
SetValue(ExecutedProperty, value);
}
}
// Make Command a dependency property so it can use databinding.
public static readonly DependencyProperty CanExecuteProperty =
DependencyProperty.Register(
"CanExecute",
typeof(object),
typeof(CommandListBox),
new PropertyMetadata((object)null));
public object CanExecute
{
get
{
return (object)GetValue(CanExecuteProperty);
}
set
{
SetValue(CanExecuteProperty, value);
}
}
// Make CommandTarget a dependency property so it can use databinding.
public static readonly DependencyProperty CommandTargetProperty =
DependencyProperty.Register(
"CommandTarget",
typeof(IInputElement),
typeof(CommandListBox),
new PropertyMetadata((IInputElement)null));
public IInputElement CommandTarget
{
get
{
return (IInputElement)GetValue(CommandTargetProperty);
}
set
{
SetValue(CommandTargetProperty, value);
}
}
// Make CommandParameter a dependency property so it can use databinding.
public static readonly DependencyProperty CommandParameterProperty =
DependencyProperty.Register(
"CommandParameter",
typeof(object),
typeof(CommandListBox),
new PropertyMetadata((object)null));
public object CommandParameter
{
get
{
return (object)GetValue(CommandParameterProperty);
}
set
{
SetValue(CommandParameterProperty, value);
}
}
// Command dependency property change callback.
private static void CommandChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
CommandListBox clb = (CommandListBox)d;
clb.HookUpCommand((ICommand)e.OldValue,(ICommand)e.NewValue);
}
// Add a new command to the Command Property.
private void HookUpCommand(ICommand oldCommand, ICommand newCommand)
{
// If oldCommand is not null, then we need to remove the handlers.
if (oldCommand != null)
{
RemoveCommand(oldCommand, newCommand);
}
AddCommand(oldCommand, newCommand);
}
// Remove an old command from the Command Property.
private void RemoveCommand(ICommand oldCommand, ICommand newCommand)
{
EventHandler handler = CanExecuteChanged;
oldCommand.CanExecuteChanged -= handler;
//newCommand.Execute(null);
//newCommand.CanExecute(null);
}
// Add the command.
private void AddCommand(ICommand oldCommand, ICommand newCommand)
{
EventHandler handler = new EventHandler(CanExecuteChanged);
canExecuteChangedHandler = handler;
if (newCommand != null)
{
newCommand.CanExecuteChanged += canExecuteChangedHandler;
//newCommand.Execute(Executed);
//newCommand.CanExecute(CanExecute);
}
}
private void CanExecuteChanged(object sender, EventArgs e)
{
if (this.Command != null)
{
RoutedCommand command = this.Command as RoutedCommand;
// If a RoutedCommand.
if (command != null)
{
if (command.CanExecute(CommandParameter, CommandTarget))
{
this.IsEnabled = true;
}
else
{
this.IsEnabled = false;
}
}
// If a not RoutedCommand.
else
{
if (Command.CanExecute(CommandParameter))
{
this.IsEnabled = true;
}
else
{
this.IsEnabled = false;
}
}
}
}
// Keep a copy of the handler so it doesn't get garbage collected.
private static EventHandler canExecuteChangedHandler;
}
}
and in my WinMain.xaml:
<Classes:CommandListBox x:Name="LayoutListBox"
Command="{x:Static local:WinMain.rcmd}"
<!-- These lines doesn't work I explain it following
Executed="CommandBinding_Executed"
CanExecute="CommandBinding_CanExecute"
-->
... >
<...>
</Classes:CommandListBox>
and window code behind:
public WinMain()
{
InitializeComponent();
// Command binding. If I don't do this Executed and CanExecute are not executed
CommandBindings.Add(new CommandBinding(rcmd,
CommandBinding_Executed, CommandBinding_CanExecute));
}
public static RoutedCommand rcmd = new RoutedCommand();
// ExecutedRoutedEventHandler
private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
// Do stuff
}
// CanExecuteRoutedEventHandler
private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = !cBgWorkers.isRunning;
//if (LayoutListBox != null) LayoutListBox.IsEnabled = !cBgWorkers.isRunning;
}
but I have the same problem as the another solution. If I don't place the last line (here appears commented in CommandBinding_CanExecute) the listbox doesn't enable automatically by wpf when background worker finishes. If I put this line it works. What's happens?
Another thing, as you can see in my code snippet I would like to do the same as I do with a button where you can indicate command, executed and canexecute. I have registered them in the class, and in listbox I checked to pass the methods but it didn't work. How can I do this?
Thanks very much.
Take a look at attached behaviors.
According to the first question I posted, using CommandBindings in listbox it doesn't work. The implementation of CanExecute was:
private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = !cBgWorkers.isRunning;
}
By doing WPF doesn't enable/disabled the listbox control automatically depending on the background worker state (Running or not) and I don't understand why because I have other controls like buttons with commands binded and WPF automatically enable/disable them.
So I have done the following modification:
private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = !cBgWorkers.isRunning;
if (LayoutListBox != null) LayoutListBox.IsEnabled = !cBgWorkers.isRunning;
}
Now, it works. Listbox is enable when no background worker is running and disabled otherwise bu what I don't like is the last line placed into the method in where I enable/disable manually the property isEnabled of the listbox. It is inefficient so I would like to change isEnabled property of the listbox only when CanExecute changes its value. As far as I know there is a event to do this, it is CanExecuteChanged but I don't know how to implement it. Any ideas?
Now, after trying several solutions, I am implementing the Mike's solution because I think it is easier and clearer and it can be re-used for other controls with only a few changes.
I haven't been able the whole thread. It's quite long. Anyway, I thought you want to put a command on a ListBoxItem? From what I see, you inherited from ListBox. You do not need to specify the Executed and CanExecute properties of the ICommandSource. This should be specified in your RoutedCommand, not in your custom control. To get your command executed, you need to provide an event handler in your custom control. As an example, if an item gets selected, then you execute the command. Here's an example.
protected override void OnSelected(RoutedEventArgs e)
{
base.OnSelected(e);
if (this.Command != null)
{
RoutedCommand command = Command as RoutedCommand;
if (command != null)
{
command.Execute(CommandParameter, CommandTarget);
}
else
{
((ICommand)Command).Execute(CommandParameter);
}
}
}

How can I toggle the main menu visibility using the Alt key in WPF?

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); }
}
}
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}}
/>
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);
}
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).
See my answer to the following thread:
How to make WPF MenuBar visibile when ALT-key is pressed?
There I describe how to solve your problem with the class InputManager (from namespace System.Windows.Input).
You can register the classes events EnterMenuMode and LeaveMenuMode.

Resources