Skip navigation.

Syndicate

Syndicate content

User login

WTF is wrong with WPF focus!?

There’s something badly broken about Windows Presentation Foundation focus. I’ve read that WPF implements its own concept of focus, and at the high level a WPF element tree is just a single HWND, and the WPF elements are rendered therein.

Here’s an experiment for you to try on your own: Create a simple XAML Window. Populate it with user controls. Now, try to get the first user control in the window to receive focus (keyboard and logical) when you’re window starts up. The FocusSample does it with a Button, which seems to work OK, but with a UserControl you’re out of luck. Even after setting Focusable to true, it doesn’t work. Yet, you can Tab through the focusable controls without problem.

First, you’ll try calling Keyboard.Focus() from within the Loaded event, but if you put trace output in the OnIsKeyboardFocusWithinChanged method of the user control, you’ll see that the call works, but it reversed again. Yes, it seems something about the window creation process after the Loaded event resets the keyboard focus, yet for some reason Button controls are impervious. TextBoxs may be as well; I’ve not tried.

In the end, I had to come up with a shameful hack. Behold, FocusHelper:

static class FocusHelper
{
    private delegate void MethodInvoker();

    public static void Focus(UIElement element)
    {
        //Focus in a callback to run on another thread, ensuring the main UI thread is initialized by the
        //time focus is set
        ThreadPool.QueueUserWorkItem(delegate(Object foo) {
            UIElement elem = (UIElement)foo;
            elem.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
                (MethodInvoker)delegate()
            {
                elem.Focus();
                Keyboard.Focus(elem);
            });                
        }, element);
    }
}

Don’t get all holier-than-thou. War makes a man do things he’d never dream of doing otherwise. So does WPF programming.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Agreed

I completely agree, something is messed up with WPF focus. I found this snippet in the docs:

“When setting initial focus at application startup, the element to receive focus must be connected to a PresentationSource and the element must have Focusable and IsVisible set to true. The recommended place to set initial focus is in the Loaded event handler. A Dispatcher callback can also be used by calling Invoke or BeginInvoke.”

They give no further explanation as to how the element “must be connected to a PresentationSource,” or why a dispatcher callback would even be necessary.

Anyhow, thanks for the example — they failed to give one of how to use a dispatcher for this.

-Doug

Worked for me

I was trying to do this in a CAB environment to no avail. Your solution works. There’s got to be a better way …

Consider adding a handler

Consider adding a handler for the PreviewGotKeyboardFocused event onthe UserControl so it could delegate focus correctly.

    private void UserControl_PreviewGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
    {
        if (e.OriginalSource == sender)
        {
            tb.Focus();
            e.Handled = true;
        }
    }

In addition you’d also need to set Focusable to true on the UserControl.

Lastly you can add a Loaded event handler to the Page and set the initial focus to the desired UserControl instance.

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        tb1.Focus();
    }