Introduction
I had a task to set focus on the first control of a RadTilePane
that was very dynamic. By this, I mean that the control was the Content
of a ContentControl
using a DataTemplate
with a DataType
that used the DataContext
to determine the DataTemplate
. I read everything, and must have tried everything but nothing worked. Controls have a Focus()
method and there is also the FocusManager
. I am sure that the Focus()
method uses the FocusManager
in some way to give the control focus. Finally, I started using the GotFocus
event, the FocusManager
. GetFocusedElement() and the Debug.Print
method to try to understand what was happening. I tried setting the Focus
on the Loaded
and Initialized
events for the UserControl
, but neither worked. To make things even weirder, that was control that was getting focus, but is seemed like it was the last one being created. Finally, I decided to try a delay and that worked.
Using the Code
This is what I ended up putting in the constructor of the UserControl
:
Initialized += (sender, args) =>
{
var t = Task.Run(() => Task.Delay(250)).ContinueWith(x =>
{
_password.Focus();
}, TaskScheduler.FromCurrentSynchronizationContext());
};
and it worked.
Conclusion
Before I found this solution, I had struggled with the focus issue numerous times, especially since it was significant enough to the customer for me to spend so much time on it. I will no longer avoid the WPF after this since I understand that the FocusManager
suffers from contention with the creation of the VisualTree
. I would have thought that Microsoft would have dealt with any issues of timing that would require any such code to be used by developers, but, again, I am wrong. Maybe this will help you quickly solve your focus problem. I set 250 milliseconds for the delay since this seemed that it was short enough that it should not cause any usability issues. A second I think is too long.
Also want to note how clean and easy the implementation is using TPL, which provides a Task.Run
, ContinueWith
, and a Task.Delay
, along with the TaskScheduler.FromCurrentSynchronizationContext()
. It seems that people still rely heavily on the BackgroundWorker
, and I cannot understand why.
History
- 08/25/2015: First version
Has been working as a C# developer on contract for the last several years, including 3 years at Microsoft. Previously worked with Visual Basic and Microsoft Access VBA, and have developed code for Word, Excel and Outlook. Started working with WPF in 2007 when part of the Microsoft WPF team. For the last eight years has been working primarily as a senior WPF/C# and Silverlight/C# developer. Currently working as WPF developer with BioNano Genomics in San Diego, CA redesigning their UI for their camera system. he can be reached at qck1@hotmail.com.