The following events can be used, but, they must be attach for each element:
GotKeyboardFocus, LostKeyboardFocus
Is there a way in .NET WPF to globally detect if
You can hook to the tunneling preview events:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="350" Width="525"
PreviewGotKeyboardFocus="Window_PreviewGotKeyboardFocus"
PreviewLostKeyboardFocus="Window_PreviewLostKeyboardFocus">
....
This way, as shown above, the window would be notified before all descendants when any of the descendants gets or loses the keyboard focus.
Read this for more information.
You can do this in any class with this:
//In the constructor
EventManager.RegisterClassHandler(
typeof(UIElement),
Keyboard.PreviewGotKeyboardFocusEvent,
(KeyboardFocusChangedEventHandler)OnPreviewGotKeyboardFocus);
...
private void OnPreviewGotKeyboardFocus(object sender,
KeyboardFocusChangedEventArgs e)
{
// Your code here
}
Have a look at how Microsoft trigger CommandManager.RequerySuggested
event when focus changes: they subscribe to InputManager.PostProcessInput event.
ReferenceSource
Simple example:
static KeyboardControl()
{
InputManager.Current.PostProcessInput += InputManager_PostProcessInput;
}
static void InputManager_PostProcessInput(object sender, ProcessInputEventArgs e)
{
if (e.StagingItem.Input.RoutedEvent == Keyboard.GotKeyboardFocusEvent ||
e.StagingItem.Input.RoutedEvent == Keyboard.LostKeyboardFocusEvent)
{
KeyboardFocusChangedEventArgs focusArgs = (KeyboardFocusChangedEventArgs)e.StagingItem.Input;
KeyboardControl.IsOpen = focusArgs.NewFocus is TextBoxBase;
}
}
This also works in multi-window applications.
You can add a routed event handler to your main window and specify you're interested in handled events.
mainWindow.AddHandler(
UIElement.GotKeyboardFocusEvent,
OnElementGotKeyboardFocus,
true
);