I have a WPF UserControl that contains a StackPanel that is made visible as a result of a state change. When the StackPanel becomes visible, I want to set the keyboard focus to a particular child TextBox. I have found (after a lot of trial and error) that the call to TextBox.Focus() will fail to set focus (and returns false) unless I wrap that call in a BeginInvoke call as shown here:
private void CtlClientLookupPanel_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) {
LogThreadMsg(string.Format("CtlClientLookupPanel_IsVisibleChanged to {0}", CtlClientLookupPanel.Visibility));
if (CtlClientLookupPanel.Visibility == Visibility.Visible) {
Dispatcher.BeginInvoke((ThreadStart)delegate {
bool gotFocus = CtlClientSearchText.Focus();
LogThreadMsg(string.Format("CtlClientSearchText.Focus() returned {0}", gotFocus));
});
}
}
private void LogThreadMsg(string msg) {
string fullMsg = string.Format("Thread: {0} - {1}", Thread.CurrentThread.ManagedThreadId, msg);
System.Diagnostics.Trace.WriteLine(msg);
}
Both LogThreadMsg calls indicate they are on the same (UI) thread as shown here:
[5232] Thread: 1 - CtlClientLookupPanel_IsVisibleChanged to Visible
[5232] Thread: 1 - CtlClientSearchText.Focus() returned True
So why is this "hack" needed? It seems to be some sort of timing issue and I was looking for a downstream event that perhaps would be a better place to call Focus() without resorting to this, but haven't found it. Can anyone explain what's going on here?