Если Вы пытаетесь применять WPF не в абсолютно новом, а в прожившем какое-то время проекте, то наверняка столкнетесь с необходимостью взаимодействия между кусочками старого интерфейса на WindowsForms и новым интерфейсом WPF. Так и я некоторое время назад столкнулся с этой проблемой.
Задача заключалась в усовершенствовании части системы, которая включала в себя интерфейс на WindowsForms с несколькими вкладками, каждая из которых содержала UserControl. Переход на WPF следовало осуществить постепенно заменяя старые WindowsForms элементы новыми. Первым делом я создал макет бедующего приложения - окно с TabControl и две вкладки одна для WPF, другая для WindowsForms. На вкладке с WindowsForms размещен UserControl с несколькими элементами управления, занимающий всю вкладку.
<TabControl SelectedIndex>
<TabItem Header="WPF">
<WrapPanel>
<Button TabIndex="1">The Button</Button>
<TextBox TabIndex="0">The Text Box</TextBox>
</WrapPanel>
</TabItem>
<TabItem Header="Windows Form" x:Name="windowsFormsTab">
<integration:WindowsFormsHost>
<this:TestControl x:Name="windowsFormsControl" />
</integration:WindowsFormsHost>
</TabItem>
</TabControl>
В старом UserControl содержалось текстовое поле, на которое должен был быть установлен фокус ввода при выборе содержащей его вкладки. В WindowsForms эта проблема решалась обработкой события VisibleChanged класса UserControl.
if (Visible)
{
// Необходимо было также выделить все содержимое
textBox.SelectAll();
textBox.Focus();
}
В новом приложении этот подход работать перестал. Более того, при переключении на окна других приложений элементы WindowsForms безвозвратно теряли фокус.
Попытка обрабатывать события Selector.Selected или GotFocus элемента TabItem не приблизили к желаемой цели. Оказалось что эти события происходят слишком рано и после этого UserControl получает массу сообщений и в результате теряет фокус. Тоже самое касается и события Activated окна WPF.
Потратив кучу времени на поиск решения я не нашел ничего кроме констатации факта существования данной проблемы. Но решение все же нашлось. Решение ЖУТКОЕ, крайне ненадежное, но все же в 99% случаев приводящее к желаемому результату – отложить установку фокуса в UserControl на некоторое время.
private void SetFocuToWindowsForms()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object o)
{
//Ждем пока WPF проделает
//все что хочет с нашим UserControl
Thread.Sleep(100);
windowsFormsControl.Invoke(new Func<bool>(windowsFormsControl.Focus));
}));
}
private void WpfWindow_Activated(object sender, EventArgs e)
{
if (wfTab.IsSelected)
{
SetFocuToWindowsForms();
}
}
private void windowsFormsTab_Selected(object sender, RoutedEventArgs e)
{
SetFocuToWindowsForms();
}
Повторюсь еще раз, что этот код может не работать в некоторых ситуация, но другого решения найти пока не удалось.