WPF and initial focus

Viewed 98560

It seems that when a WPF application starts, nothing has focus.

This is really weird. Every other framework I've used does just what you'd expect: puts initial focus on the first control in the tab order. But I've confirmed that it's WPF, not just my app -- if I create a new Window, and just put a TextBox in it, and run the app, the TextBox doesn't have focus until I click on it or press Tab. Yuck.

My actual app is more complicated than just a TextBox. I have several layers of UserControls within UserControls. One of those UserControls has Focusable="True" and KeyDown/KeyUp handlers, and I want it to have the focus as soon as my window opens. I'm still somewhat of a WPF novice, though, and I'm not having much luck figuring out how to do this.

If I start my app and press the Tab key, then focus goes to my focusable control, and it starts working the way I want. But I don't want my users to have to hit Tab before they can start using the window.

I've played around with FocusManager.FocusedElement, but I'm not sure which control to set it on (the top-level Window? the parent that contains the focusable control? the focusable control itself?) or what to set it to.

What do I need to do to get my deeply-nested control to have initial focus as soon as the window opens? Or better yet, to focus the first focusable control in the tab order?

12 Answers

I had the bright idea to dig through Reflector to see where the Focusable property is used, and found my way to this solution. I just need to add the following code to my Window's constructor:

Loaded += (sender, e) =>
    MoveFocus(new TraversalRequest(FocusNavigationDirection.First));

This will automatically select the first control in the tab order, so it's a general solution that should be able to be dropped into any window and Just Work.

I found another possible solution. Mark Smith posted a FirstFocusedElement markup extension for use with FocusManager.FocusedElement.

<UserControl x:Class="FocusTest.Page2"
    xmlns:FocusTest="clr-namespace:FocusTest"
    FocusManager.FocusedElement="{FocusTest:FirstFocusedElement}">

After having a 'WPF Initial Focus Nightmare' and based on some answers on stack, the following proved for me to be the best solution.

First, add your App.xaml OnStartup() the followings:

EventManager.RegisterClassHandler(typeof(Window), Window.LoadedEvent,
          new RoutedEventHandler(WindowLoaded));

Then add the 'WindowLoaded' event also in App.xaml :

void WindowLoaded(object sender, RoutedEventArgs e)
    {
        var window = e.Source as Window;
        System.Threading.Thread.Sleep(100);
        window.Dispatcher.Invoke(
        new Action(() =>
        {
            window.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));

        }));
    }

The threading issue must be use as WPF initial focus mostly fails due to some framework race conditions.

I found the following solution best as it is used globally for the whole app.

Hope it helps...

Oran

If you are like me, and you are using some frameworks that, somehow, mess up with the basic focus behaviors, and make all solutions above irrelevant, you can still do this :

1 - Note the element which get the focus (whatever it is!)

2 - Add this in your code behind xxx.xaml.cs

private bool _firstLoad;

3 - Add this on the element which get the first focus :

GotFocus="Element_GotFocus"

4 - Add the Element_GotFocus method in the code behind, and specify the WPF named element who need the first focus :

private void Element_GotFocus(object sender, RoutedEventArgs e)
{
    if(_firstLoad)
    {
        this.MyElementWithFistFocus.Focus();
        _firstLoad = false;
    }
}

5 - Manage the Loaded event

in XAML

Loaded="MyWindow_Loaded"   

in xaml.cs

private void MyWindow_Loaded(object sender, RoutedEventArgs e)
{
        _firstLoad = true;
        this.Element_GotFocus(null, null);
}

Hope this will help as a last resort solution

Related