#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.