Страницы

Поиск по вопросам

четверг, 13 февраля 2020 г.

Выделение текста при клике на TextBox

#c_sharp #wpf


Требуется при клике на TextBox выделять текст. 
Собственно box-ы содержат пояснение, что вводить. Удалять по-умолчанию его не нужно.
Но выделить перед введением текста, чтобы ускорить ввод, стоит.

Что пробовал:

textBox_name.SelectionStart = 0;
textBox_name.SelectionLength = textBox_name.Text.Length;


и

textBox_name.SelectAll(); 


По какой-то причине не срабатывает. Чувствую где-то рядом, но видимо что-то не учитываю.
    


Ответы

Ответ 1



Если внимательно присмотреться к элементу TextBox, то можно заметить, что при первом клике на нем происходит следующее: элемент приобретает фокус и каретка курсора встает на месте клика пользователя. Когда мы пытаемся по события фокуса просто выделить весь текст внутри: ... text = new TextBox(); text.Text = "Sample text"; text.GotFocus += text_GotFocus; ... ... private void text_GotFocus(object sender, RoutedEventArgs e) { TextBox text = sender as TextBox; if(text != null) text.SelectAll(); } ... Происходит следующее. Наш текстовый элемент получает событие (Preview)MouseLeftButtonDown, которое вызывает фокус и только потом устанавливает каретку в нужное положение, тем самым снимая наше выделение от события фокуса. Эта та причина, по которой при получении элементом фокуса от клавиатуры, выделение срабатывает нормально, а при клике нет. Одним из вариантов решения является самому отловить событие нажатия мыши и обработать его, но у элемента TextBox отсутствуют какие-либо события мышки кроме (preview)DoubleMouseClick. Для того, что бы решить эту проблему, используется регистрация события на все элементы TextBox через EventManager.RegisterClassHandler. При этом событие останавливается и элементу передается событие фокуса. ... EventManager.RegisterClassHandler(typeof(TextBox), UIElement.PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(StopTextBoxClick), true); ... ... private void StopTextBoxClick(object sender, MouseButtonEventArgs e) { TextBox text = sender as TextBox; if(text != null){ e.Handled = true; text.Focus(); } } ... В данном варианте остается одна проблема, теперь каждый раз срабатывает событие фокуса и текст остается выделенным всегда, а мышь не работает. Последней правкой является остановка событие только тогда, когда фокус у элемента еще не получен. Для этого можно использовать свойство IsFocused, но поскольку элемент может содержать еще какие-то вложенные элементы, используется IsKeyboardFocusWithin. Кстати, событие получения фокуса можно установить не через text.GotFocus += text_GotFocus, а через тот же EventManager.RegisterClassHandler. Разницы в данном случае не будет. Вот мы и приходим к такому коду: ... text = new TextBox(); text.Text = "Sample text"; ... ... EventManager.RegisterClassHandler(typeof(TextBox), UIElement.PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(StopTextBoxClick), true); EventManager.RegisterClassHandler(typeof(TextBox), UIElement.GotFocusEvent, new RoutedEventHandler(text_GotFocus), true); ... ... private void text_GotFocus(object sender, RoutedEventArgs e) { TextBox text = sender as TextBox; if(text != null) text.SelectAll(); } private void StopTextBoxClick(object sender, MouseButtonEventArgs e) { TextBox text = sender as TextBox; if (text != null && !text.IsKeyboardFocusWithin) { e.Handled = true; text.Focus(); } } ... И все из-за того, что событие клика так работает - само устанавливает фокус и потом устанавливает каретку, снимая наши попытки выделения. P.S. Опять же, событие действует на все элементы TextBox, поэтому если вам этого не надо, нужно в коде как-то ограничить события. Для этого внутри проверки if (text != null && !text.IsKeyboardFocusWithin) можно уже проверять дополнительные условия и свойства.

Ответ 2



Более простой вариант: XAML C# private bool isFocused = false; private void TextBox_GotFocus(object sender, RoutedEventArgs e) { isFocused = true; } private void TextBox_SelectionChanged(object sender, RoutedEventArgs e) { if (isFocused) { isFocused = false; (sender as TextBox).SelectAll(); } }

Ответ 3



Если в первоначальном варианте selectall() исправить на select(), то все работает без костылей.

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

Отправить комментарий