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.
June 29th, 2007 - 08:51
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
July 27th, 2007 - 16:10
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 . . .
August 6th, 2007 - 19:22
Consider adding a handler for the PreviewGotKeyboardFocused event onthe UserControl so it could delegate focus correctly.
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.
May 30th, 2008 - 23:49
Have you tried setting focus in the ContentRendered event instead of the Loaded event?
July 28th, 2008 - 03:17
using mentioned above using the Loaded events works well
public IntercomPad()
{
InitializeComponent();
Loaded += new RoutedEventHandler(IntercomPad_Loaded);
}
void IntercomPad_Loaded(object sender, RoutedEventArgs e)
{
//FocusManager.SetFocusedElement(this, tPhoneNumber);
IInputElement ie = Keyboard.Focus(tPhoneNumber);
}
November 18th, 2008 - 21:32
Yeah, WPF is messed up. But thank you … over a year later… your snippet saved me hours of hassle!
March 23rd, 2009 - 17:14
I didn’t understand why I set Focus() inside LostFocus event is ended with stack overflow. Your post saves alot of my works.
March 26th, 2009 - 16:25
This works too:
///
/// Focuses the specified UI element.
///
/// The UI element.
public static void DelayedFocus ( this UIElement uiElement )
{
uiElement.Dispatcher.BeginInvoke(
new Action(delegate
{
uiElement.Focusable = true;
uiElement.Focus();
Keyboard.Focus(uiElement);
}),
DispatcherPriority.Render);
}
July 31st, 2009 - 07:10
had similar feeling the focus is messed in wpf. tried some stuff. as you can read here: http://www.batteryslave.com/2009/05/what-is-wrong-with-focus-in-wpf/
i added some testcode. some stuff from above worked half. but not in the examples in my article…too bad
batteryslave
September 9th, 2009 - 08:19
DontFocusTooEarly is right – create a method
“private void Content_Rendered(object sender, EventArgs e)”
and in the XAML tag, put:
ContentRendered=”Content_Rendered”
then in the Content_Rendered method you have just created, use Keyboard.Focus(object); , or whatever else you want to do with focus.
November 16th, 2009 - 05:00
hi can you explain us how to use it in the XAML
April 28th, 2010 - 18:51
Thanks for the quick solution–not elegant but it works and sometimes that’s what counts when it comes to WPF.
July 21st, 2010 - 11:47
Your last three lines made my day a little less painful. Thank you for that.