WPF MyTextBox.Focus() возвращает true, но кажется, что окно на самом деле имеет фокус

#c# #wpf #focus #styling

#c# #wpf #фокус #стиль

Вопрос:

Поэтому, когда открывается мое окно, в событии Loaded я устанавливаю

 MyTextBox.Focus();
 

и это работает нормально, визуальный фокус есть, курсор мигает, я могу печатать, без проблем. Щелкните узел в древовидном представлении, в котором я хочу изменить текст текстового поля и перефокусировать текстовое поле, чтобы пользователь мог продолжать печатать. Я вызываю:

     MyTextBox.Focus();
 

еще раз. Визуальный фокус НЕ отображается в текстовом поле, а курсор ОТСУТСТВУЕТ в текстовом поле. Однако клавиатура.FocusedElement == MyTextBox имеет значение TRUE . Две странности:

A) У меня есть кнопка [_Save] в окне. Если я просто нажимаю «S» (без модификатора Alt), эта кнопка нажата, как будто окно принимало мои нажатия клавиш!

Б) если я нажимаю TAB на клавиатуре, выбирается первый элемент управления в окне, в конце концов, я могу выбрать нужный элемент управления, и он работает отлично.

Нигде не установлены явные области фокусировки.

Кроме того, если я попробую обходы или InputManager.Текущий.ProcessInput(некоторые вкладки) или несколько других способов попытаться настроить окно так, чтобы MyTextBox правильно фокусировался, ни один из них не работает.

Это обычное приложение WPF без каких-либо специальных стилей / шаблонов, и я в своем уме!

Комментарии:

1. Вы пробовали Keyboard.Focus(MyTextBox) ?

2. Просто идея — возможно TreeView , пытается захватить фокус после щелчка — попробуйте отложить textBox.Focus(); использование Dispatcher : textBox.Dispatcher.BeginInvoke((Action)(() => textBox.Focus()));

3. @Quercus Извините, нет кубиков. Focus() возвращает true, и проверка сфокусированного элемента подтверждает, что мое текстовое поле, А НЕ древовидное изображение имеет фокус. Это просто не выглядит и не действует таким образом. Просмотр дерева не крадет фокус. Мое опубликованное решение выполняет свою работу, но спасибо за предложение.

Ответ №1:

Установите фокус обратно в текстовое поле в событии TreeView GotFocus. Пример:

XAML

         <TreeView x:Name="tw" GotFocus="tw_GotFocus">
            <TreeViewItem Header="twh1">
                <TreeViewItem Header="twh2" Selected="TreeViewItem_Selected"></TreeViewItem>
            </TreeViewItem>
        </TreeView>
        <TextBox x:Name="MyTextBox"/>
 

CS

     private void TreeViewItem_Selected(object sender, RoutedEventArgs e)
    {
        MyTextBox.AppendText(((TreeViewItem)sender).Header.ToString());
        MyTextBox.CaretIndex = MyTextBox.Text.Length;
    }

    private void tw_GotFocus(object sender, RoutedEventArgs e)
    {
        MyTextBox.Focus();
    }
 

Комментарии:

1. Извините, но это просто не работает. Кроме того, я хочу, чтобы у treeview был фокус, чтобы пользователи могли прокручивать его с помощью клавиатуры и тому подобное.

Ответ №2:

ХОРОШО, в прошлом у меня была эта проблема со старым приложением WPF на основе VSTO, и я адаптировал решение, которое я придумал, для работы и здесь. Вот метод расширения:

 using System.Threading.Tasks;
using System.Windows;

namespace My.Extensions
{
    public static class UiElementExtensions
    {
        /// <summary>
        /// Use when the normal Focus() just refuses to cooperate.
        /// Don't use rapidly in succession unless you rewrite the whole thing to return a Task.
        /// </summary>
        /// <param name="it">The UIElement to give focus.</param>
        /// <param name="delay">Try less than 20 ms at your end users' peril.</param>
        public static void FocusHarder(this UIElement it, int delay = 20)
        {
            var w = new Window { Width = 0, Height = 0, Visibility = Visibility.Hidden };
            w.Loaded  = async (_, _) =>
            {
                await Task.Delay(delay);
                it.Focus();
                w.Close();
            };
            w.Show();
        }
    }
}
 

Используйте его вместо .Focus(), например:

 MyTextBox.FocusHarder();
 

Я знаю, что это хак, но будь я проклят, если он не работает очень надежно. Я не уверен, какой на самом деле должна быть задержка в 20 мс, но в моем тестировании меньшее значение иногда не работает в системах некоторых конечных пользователей.

Я начинаю думать, что это почти повсеместная ошибка синхронизации WPF.