simo
simo

Reputation: 24600

Is it possible to detect Keyboard focus events globally?

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 the focused element changed ? without having to add event listeners for all possible elements ?

Upvotes: 15

Views: 9940

Answers (4)

nevermind
nevermind

Reputation: 2448

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.

Upvotes: 3

Vaccano
Vaccano

Reputation: 82517

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

}

Upvotes: 21

user610650
user610650

Reputation:

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.

Upvotes: 6

Nicolas Repiquet
Nicolas Repiquet

Reputation: 9265

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
);

Upvotes: 5

Related Questions