Текстовое поле SelectAll на вкладке, но не щелчок мышью
Так что давайте скажем, что у меня есть форма WPF с несколькими текстовыми полями, если вы вставляете текст в текстовое поле, и в нем уже есть что-то, я хочу выделить весь текст в этом поле, чтобы при наборе текста был удален этот текст. Если вы нажмете мышкой на поле, это, вероятно, означает, что вы хотите где-то изменить письмо, поэтому не выделяйте все в этом случае. Кажется, достаточно легко, но хорошее решение, которое до сих пор ускользало от меня. Вот что у меня до сих пор, что очень близко к работе, но не совсем идеально.
<Style x:Key="TextBoxStyle" TargetType="TextBox">
<EventSetter Event="GotKeyboardFocus" Handler="EventSetter_OnHandler" />
</Style>
private void EventSetter_OnHandler(object sender, RoutedEventArgs e)
{
TextBox txt = sender as TextBox;
if (txt != null) txt.SelectAll();
}
Итак, когда поле получает фокус клавиатуры, он выбирает все, поэтому вставляя текст в текстовое поле, он отлично отображает текст. Однако, если щелчок мышью, этот метод также вызывается, что также подчеркивает текст, но щелчок затем помещает курсор туда, куда нажата кнопка мыши. Так функционально это прекрасно, но меня все равно беспокоит, что он мерцает, выбирая все, когда кликает мышкой. Любой лучший способ сделать это, или поставить какую-то проверку в моем случае, чтобы узнать, что я получил фокус клавиатуры с помощью мыши, а не вкладки?
Ответы
Ответ 1
До сих пор, к сожалению, не было никакого чистого решения, одна вещь, которую вы могли бы сделать, это просто проверить состояние мыши:
var tb = (TextBox)sender;
if (Mouse.LeftButton != MouseButtonState.Pressed)
tb.SelectAll();
Но на самом деле есть лучший способ, так как фокус сдвигается по клавише вниз, вы можете проверить клавиатуру. Я бы рекомендовал использовать соответствующую подпись для обработчика GotKeyboardFocus
для получения соответствующих событий-аргументов:
private void TextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
if (e.KeyboardDevice.IsKeyDown(Key.Tab))
((TextBox)sender).SelectAll();
}
В этот момент вы все еще можете увидеть, что какой-то выбор очищается при щелчке, но это только потому, что предыдущий выбор только скрывается, если он не сфокусирован. Вы всегда можете удалить выделение в LostKeyboardFocus
, чтобы предотвратить это (например, ((TextBox)sender).Select(0, 0)
).
Ответ 2
Вы можете попробовать проверить, присутствует ли мышь в текстовом поле, когда происходит событие Focus, и проверьте мышь ButtonButtonState. Это не идеально, но должно быть близко к тому, что вы ищете.
private void EventSetter_OnHandler(object sender, RoutedEventArgs e)
{
TextBox txt = sender as TextBox;
Point position = Mouse.GetPosition(txt);
// if Mouse position is not in the TextBox Client Rectangle
// and Mouse Button not Pressed.
if((!(new Rect(0,0,txt.Width,txt.Height)).Contains(position)) || ( Mouse.LeftButton != MouseButtonState.Pressed))
if (txt != null) txt.SelectAll();
}
и как H.B. Указав, вы можете попробовать использовать свойство txt.IsMouseOver, чтобы определить, находится ли курсор внутри прямоугольника TextBox Client Rectangle. Он выглядит намного чище.
private void EventSetter_OnHandler(object sender, RoutedEventArgs e)
{
TextBox txt = sender as TextBox;
if( !txt.IsMouseOver || Mouse.LeftButton != MouseButtonState.Pressed)
if (txt != null) txt.SelectAll();
}
Ответ 3
Вы можете захватить последнюю нажатую клавишу и сравнить ее с вашим событием
private Key lastKey;
protected override void OnKeyDown(KeyEventArgs e)
{
lastKey = e.Key;
base.OnKeyDown(e);
}
и в вашем случае:
private void EventSetter_OnHandler(object sender, RoutedEventArgs e)
{
if(lastKey != Key.Tab)
return;
TextBox txt = sender as TextBox;
if (txt != null) txt.SelectAll();
}
Это не идеально, потому что они могли ударить вкладку (не вставляя в ваш контроль), а затем щелкнуть по ней своим контролем. Но он будет работать большую часть времени.
Ответ 4
Вы можете использовать прикрепленный шаблон поведения
public class Behaviors
{
public static readonly DependencyProperty SelectTextOnFocusProperty = DependencyProperty
.RegisterAttached("SelectTextOnFocus", typeof(bool), typeof(Behaviors), new FrameworkPropertyMetadata(false, GotFocus));
public static void SetSelectTextOnFocus(DependencyObject obj, bool value)
{
obj.SetValue(SelectTextOnFocusProperty, value);
}
private static void GotFocus(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var textbox = d as TextBox;
if (null == textbox) return;
textbox.GotKeyboardFocus += SelectTextOnFocus;
textbox.GotMouseCapture += SelectTextOnFocus;
}
private static void SelectTextOnFocus(object sender, RoutedEventArgs e)
{
if (!(sender is TextBox)) return;
((TextBox)sender).SelectAll();
}
}
в вашем xaml нужно только
xmlns:my="clr-namespace:Namespace;assembly=Rkmax"
вы можете использовать в текстовом поле, например
<TextBox my:Behaviors.SelectTextOnFocus="True" />
вся эта работа для события мыши и клавиатуры
Ответ 5
Я много искал для решения, я нашел пару решений для selectall
Но проблема заключается в том, когда мы делаем правый щелчок и делаем вырезание/копирование после выбора части текста из текстового поля, он выбирает все, даже я выбрал часть текста. Исправить это можно здесь. Просто добавьте приведенный ниже код в событие выбора клавиатуры.
Это сработало для меня.
private static void SelectContentsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is TextBox)
{
TextBox textBox = d as TextBox;
if ((e.NewValue as bool?).GetValueOrDefault(false))
{
textBox.GotKeyboardFocus += OnKeyboardFocusSelectText;
}
else
{
textBox.GotKeyboardFocus -= OnKeyboardFocusSelectText;
}
}
}
private static void OnKeyboardFocusSelectText(object sender, KeyboardFocusChangedEventArgs e)
{
if (e.KeyboardDevice.IsKeyDown(Key.Tab))
((TextBox)sender).SelectAll();
}