Ответ 1
Не знаю, почему он теряет выделение в событии GotFocus.
Но одно решение - сделать выбор в событиях GotKeyboardFocus и GotMouseCapture. Таким образом, он всегда будет работать.
Если я вызываю SelectAll
из обработчика события GotFocus
, он не работает с мышью - выбор исчезает, как только мышь отпускается.
РЕДАКТИРОВАТЬ: Людям нравится ответ Доннеле, я постараюсь объяснить, почему мне это не понравилось, как принятый ответ.
Не знаю, почему он теряет выделение в событии GotFocus.
Но одно решение - сделать выбор в событиях GotKeyboardFocus и GotMouseCapture. Таким образом, он всегда будет работать.
У нас это так, что первый щелчок выбирает все, а другой клик идет на курсор (наше приложение предназначено для использования на планшетах с ручками).
Вы можете найти это полезным.
public class ClickSelectTextBox : TextBox
{
public ClickSelectTextBox()
{
AddHandler(PreviewMouseLeftButtonDownEvent,
new MouseButtonEventHandler(SelectivelyIgnoreMouseButton), true);
AddHandler(GotKeyboardFocusEvent,
new RoutedEventHandler(SelectAllText), true);
AddHandler(MouseDoubleClickEvent,
new RoutedEventHandler(SelectAllText), true);
}
private static void SelectivelyIgnoreMouseButton(object sender,
MouseButtonEventArgs e)
{
// Find the TextBox
DependencyObject parent = e.OriginalSource as UIElement;
while (parent != null && !(parent is TextBox))
parent = VisualTreeHelper.GetParent(parent);
if (parent != null)
{
var textBox = (TextBox)parent;
if (!textBox.IsKeyboardFocusWithin)
{
// If the text box is not yet focussed, give it the focus and
// stop further processing of this click event.
textBox.Focus();
e.Handled = true;
}
}
}
private static void SelectAllText(object sender, RoutedEventArgs e)
{
var textBox = e.OriginalSource as TextBox;
if (textBox != null)
textBox.SelectAll();
}
}
Ответ Donnelle работает лучше всего, но для того, чтобы получить новый класс для использования, это боль.
Вместо этого я регистрирую обработчики обработчиков в App.xaml.cs для всех текстовых полей в приложении. Это позволяет мне использовать ответ Donnelle со стандартным элементом управления TextBox.
Добавьте в свой App.xaml.cs следующие методы:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
// Select the text in a TextBox when it receives focus.
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.PreviewMouseLeftButtonDownEvent,
new MouseButtonEventHandler(SelectivelyIgnoreMouseButton));
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.GotKeyboardFocusEvent,
new RoutedEventHandler(SelectAllText));
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.MouseDoubleClickEvent,
new RoutedEventHandler(SelectAllText));
base.OnStartup(e);
}
void SelectivelyIgnoreMouseButton(object sender, MouseButtonEventArgs e)
{
// Find the TextBox
DependencyObject parent = e.OriginalSource as UIElement;
while (parent != null && !(parent is TextBox))
parent = VisualTreeHelper.GetParent(parent);
if (parent != null)
{
var textBox = (TextBox)parent;
if (!textBox.IsKeyboardFocusWithin)
{
// If the text box is not yet focused, give it the focus and
// stop further processing of this click event.
textBox.Focus();
e.Handled = true;
}
}
}
void SelectAllText(object sender, RoutedEventArgs e)
{
var textBox = e.OriginalSource as TextBox;
if (textBox != null)
textBox.SelectAll();
}
}
Это довольно старый, но я все равно покажу свой ответ.
Я выбрал часть ответа Donnelle (пропустил двойной щелчок), поскольку я думаю, что это создает наименьшее удивление у пользователей. Однако, как и gcores, мне не нравится необходимость создания производного класса. Но мне также не нравится gcores "on Startup...". И мне это нужно на "вообще, но не всегда".
Я реализовал это как свойство зависимой зависимости, поэтому я могу установить SelectTextOnFocus.Active=True
в xaml. Я нахожу этот путь самым приятным.
namespace foo.styles.behaviour
{
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
public class SelectTextOnFocus : DependencyObject
{
public static readonly DependencyProperty ActiveProperty = DependencyProperty.RegisterAttached(
"Active",
typeof(bool),
typeof(SelectTextOnFocus),
new PropertyMetadata(false, ActivePropertyChanged));
private static void ActivePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is TextBox)
{
TextBox textBox = d as TextBox;
if ((e.NewValue as bool?).GetValueOrDefault(false))
{
textBox.GotKeyboardFocus += OnKeyboardFocusSelectText;
textBox.PreviewMouseLeftButtonDown += OnMouseLeftButtonDown;
}
else
{
textBox.GotKeyboardFocus -= OnKeyboardFocusSelectText;
textBox.PreviewMouseLeftButtonDown -= OnMouseLeftButtonDown;
}
}
}
private static void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DependencyObject dependencyObject = GetParentFromVisualTree(e.OriginalSource);
if (dependencyObject == null)
{
return;
}
var textBox = (TextBox)dependencyObject;
if (!textBox.IsKeyboardFocusWithin)
{
textBox.Focus();
e.Handled = true;
}
}
private static DependencyObject GetParentFromVisualTree(object source)
{
DependencyObject parent = source as UIElement;
while (parent != null && !(parent is TextBox))
{
parent = VisualTreeHelper.GetParent(parent);
}
return parent;
}
private static void OnKeyboardFocusSelectText(object sender, KeyboardFocusChangedEventArgs e)
{
TextBox textBox = e.OriginalSource as TextBox;
if (textBox != null)
{
textBox.SelectAll();
}
}
[AttachedPropertyBrowsableForChildrenAttribute(IncludeDescendants = false)]
[AttachedPropertyBrowsableForType(typeof(TextBox))]
public static bool GetActive(DependencyObject @object)
{
return (bool) @object.GetValue(ActiveProperty);
}
public static void SetActive(DependencyObject @object, bool value)
{
@object.SetValue(ActiveProperty, value);
}
}
}
Для моего "общего, но не всегда" -feature я установил это свойство в True в (глобальном) TextBox-Style. Таким образом, "выбор текста" всегда "on", но я могу отключить его для каждого текстового поля.
Ниже приведены действия Blend, реализующие решение для вашего решения:
Один для прикрепления к одному текстовому блоку:
public class SelectAllTextOnFocusBehavior : Behavior<TextBox>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.GotKeyboardFocus += AssociatedObjectGotKeyboardFocus;
AssociatedObject.GotMouseCapture += AssociatedObjectGotMouseCapture;
AssociatedObject.PreviewMouseLeftButtonDown += AssociatedObjectPreviewMouseLeftButtonDown;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.GotKeyboardFocus -= AssociatedObjectGotKeyboardFocus;
AssociatedObject.GotMouseCapture -= AssociatedObjectGotMouseCapture;
AssociatedObject.PreviewMouseLeftButtonDown -= AssociatedObjectPreviewMouseLeftButtonDown;
}
private void AssociatedObjectGotKeyboardFocus(object sender,
System.Windows.Input.KeyboardFocusChangedEventArgs e)
{
AssociatedObject.SelectAll();
}
private void AssociatedObjectGotMouseCapture(object sender,
System.Windows.Input.MouseEventArgs e)
{
AssociatedObject.SelectAll();
}
private void AssociatedObjectPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if(!AssociatedObject.IsKeyboardFocusWithin)
{
AssociatedObject.Focus();
e.Handled = true;
}
}
}
И один для прикрепления к корню контейнера, содержащего несколько TextBox'ов:
public class SelectAllTextOnFocusMultiBehavior : Behavior<UIElement>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.GotKeyboardFocus += HandleKeyboardFocus;
AssociatedObject.GotMouseCapture += HandleMouseCapture;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.GotKeyboardFocus -= HandleKeyboardFocus;
AssociatedObject.GotMouseCapture -= HandleMouseCapture;
}
private static void HandleKeyboardFocus(object sender,
System.Windows.Input.KeyboardFocusChangedEventArgs e)
{
var txt = e.NewFocus as TextBox;
if (txt != null)
txt.SelectAll();
}
private static void HandleMouseCapture(object sender,
System.Windows.Input.MouseEventArgs e)
{
var txt = e.OriginalSource as TextBox;
if (txt != null)
txt.SelectAll();
}
}
Здесь очень хорошее очень простое решение на MSDN:
<TextBox
MouseDoubleClick="SelectAddress"
GotKeyboardFocus="SelectAddress"
PreviewMouseLeftButtonDown="SelectivelyIgnoreMouseButton" />
Вот код позади:
private void SelectAddress(object sender, RoutedEventArgs e)
{
TextBox tb = (sender as TextBox);
if (tb != null)
{
tb.SelectAll();
}
}
private void SelectivelyIgnoreMouseButton(object sender,
MouseButtonEventArgs e)
{
TextBox tb = (sender as TextBox);
if (tb != null)
{
if (!tb.IsKeyboardFocusWithin)
{
e.Handled = true;
tb.Focus();
}
}
}
Хотя это старый вопрос, я только что столкнулся с этой проблемой, но решил ее, используя Attached Behavior, а не Expression Behavior, как в ответе Sergey. Это означает, что мне не нужна зависимость от System.Windows.Interactivity
в Blend SDK:
public class TextBoxBehavior
{
public static bool GetSelectAllTextOnFocus(TextBox textBox)
{
return (bool)textBox.GetValue(SelectAllTextOnFocusProperty);
}
public static void SetSelectAllTextOnFocus(TextBox textBox, bool value)
{
textBox.SetValue(SelectAllTextOnFocusProperty, value);
}
public static readonly DependencyProperty SelectAllTextOnFocusProperty =
DependencyProperty.RegisterAttached(
"SelectAllTextOnFocus",
typeof (bool),
typeof (TextBoxBehavior),
new UIPropertyMetadata(false, OnSelectAllTextOnFocusChanged));
private static void OnSelectAllTextOnFocusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var textBox = d as TextBox;
if (textBox == null) return;
if (e.NewValue is bool == false) return;
if ((bool) e.NewValue)
{
textBox.GotFocus += SelectAll;
textBox.PreviewMouseDown += IgnoreMouseButton;
}
else
{
textBox.GotFocus -= SelectAll;
textBox.PreviewMouseDown -= IgnoreMouseButton;
}
}
private static void SelectAll(object sender, RoutedEventArgs e)
{
var textBox = e.OriginalSource as TextBox;
if (textBox == null) return;
textBox.SelectAll();
}
private static void IgnoreMouseButton(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
var textBox = sender as TextBox;
if (textBox == null || (!textBox.IsReadOnly && textBox.IsKeyboardFocusWithin)) return;
e.Handled = true;
textBox.Focus();
}
}
Затем вы можете использовать его в своем XAML следующим образом:
<TextBox Text="Some Text" behaviors:TextBoxBehavior.SelectAllTextOnFocus="True"/>
Я написал об этом здесь.
Я думаю, что это хорошо работает:
private void ValueText_GotFocus(object sender, RoutedEventArgs e)
{
TextBox tb = (TextBox)e.OriginalSource;
tb.Dispatcher.BeginInvoke(
new Action(delegate
{
tb.SelectAll();
}), System.Windows.Threading.DispatcherPriority.Input);
}
Если вы хотите реализовать его как метод расширения:
public static void SelectAllText(this System.Windows.Controls.TextBox tb)
{
tb.Dispatcher.BeginInvoke(
new Action(delegate
{
tb.SelectAll();
}), System.Windows.Threading.DispatcherPriority.Input);
}
И в вашем событии GotFocus:
private void ValueText_GotFocus(object sender, RoutedEventArgs e)
{
TextBox tb = (TextBox)e.OriginalSource;
tb.SelectAllText();
}
Я нашел решение выше, потому что несколько месяцев назад я искал способ сосредоточиться на данном UIElement. Я где-то обнаружил код ниже (здесь дан кредит), и он работает хорошо. Я публикую его, даже если он напрямую не связан с вопросом OP, поскольку он демонстрирует ту же схему использования Диспетчера для работы с UIElement.
// Sets focus to uiElement
public static void DelayedFocus(this UIElement uiElement)
{
uiElement.Dispatcher.BeginInvoke(
new Action(delegate
{
uiElement.Focusable = true;
uiElement.Focus();
Keyboard.Focus(uiElement);
}),
DispatcherPriority.Render);
}
Я не нашел ни одного из представленных здесь ответов, имитирующих стандартное текстовое поле Windows. Например, попробуйте щелкнуть пробел между последним символом текстового поля и правой стороной текстового поля. Большинство решений здесь всегда будут выбирать весь контент, что затрудняет добавление текста в текстовое поле.
Ответ, который я здесь представляю, ведет себя лучше в этом отношении. Это поведение (для этого требуется сборка System.Windows.Interactivity из Blend SDK). Он также может быть переписан с использованием добавленных свойств.
public sealed class SelectAllTextOnFocusBehavior : Behavior<TextBox>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.PreviewMouseLeftButtonDown += AssociatedObject_PreviewMouseLeftButtonDown;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.PreviewMouseLeftButtonDown -= AssociatedObject_PreviewMouseLeftButtonDown;
}
void AssociatedObject_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// Find the textbox
DependencyObject parent = e.OriginalSource as UIElement;
while (parent != null && !(parent is TextBox))
parent = VisualTreeHelper.GetParent(parent);
var textBox = parent as TextBox;
Debug.Assert(textBox != null);
if (textBox.IsFocused) return;
textBox.SelectAll();
Keyboard.Focus(textBox);
e.Handled = true;
}
}
Это основано на коде, который я нашел здесь.
Эта простая реализация отлично работает для меня:
void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
((TextBox) sender).SelectAll();
}
void TextBox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
var TextBox = (TextBox) sender;
if (!TextBox.IsKeyboardFocusWithin)
{
TextBox.Focus();
e.Handled = true;
}
}
Чтобы применить его ко всем TextBox
', введите следующий код после InitializeComponent();
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.GotFocusEvent, new RoutedEventHandler(TextBox_GotFocus));
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.PreviewMouseDownEvent, new MouseButtonEventHandler(TextBox_PreviewMouseDown));
в файле App.xaml
<Application.Resources>
<Style TargetType="TextBox">
<EventSetter Event="GotKeyboardFocus" Handler="TextBox_GotKeyboardFocus"/>
</Style>
</Application.Resources>
в файле App.xaml.cs
private void TextBox_GotKeyboardFocus(Object sender, KeyboardFocusChangedEventArgs e)
{
((TextBox)sender).SelectAll();
}
С помощью этого кода вы достигаете всего текстового поля в своем приложении.
Взято из здесь:
Зарегистрировать глобальный обработчик событий в файле App.xaml.cs:
protected override void OnStartup(StartupEventArgs e)
{
EventManager.RegisterClassHandler(typeof(TextBox),TextBox.GotFocusEvent,
new RoutedEventHandler(TextBox_GotFocus));
base.OnStartup(e);
}
Тогда обработчик прост как:
private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
(sender as TextBox).SelectAll();
}
У меня есть немного упрощенный ответ для этого (только с событием PreviewMouseLeftButtonDown), который, похоже, имитирует обычные функции браузера:
В xaml у вас есть текстовое поле:
<TextBox Text="http://www.blabla.com" BorderThickness="2" BorderBrush="Green" VerticalAlignment="Center" Height="25"
PreviewMouseLeftButtonDown="SelectAll" />
В codebehind:
private void SelectAll(object sender, MouseButtonEventArgs e)
{
TextBox tb = (sender as TextBox);
if (tb == null)
{
return;
}
if (!tb.IsKeyboardFocusWithin)
{
tb.SelectAll();
e.Handled = true;
tb.Focus();
}
}
Я понимаю, что это очень старое, но вот мое решение, которое основано на пространствах имен выражений/взаимодействия Microsoft и взаимодействий.
Сначала я следовал инструкциям по этой ссылке, чтобы поместить триггеры интерактивности в стиль.
Тогда это сводится к этому
<Style x:Key="baseTextBox" TargetType="TextBox">
<Setter Property="gint:InteractivityItems.Template">
<Setter.Value>
<gint:InteractivityTemplate>
<gint:InteractivityItems>
<gint:InteractivityItems.Triggers>
<i:EventTrigger EventName="GotKeyboardFocus">
<ei:CallMethodAction MethodName="SelectAll"/>
</i:EventTrigger>
<i:EventTrigger EventName="PreviewMouseLeftButtonDown">
<ei:CallMethodAction MethodName="TextBox_PreviewMouseLeftButtonDown"
TargetObject="{Binding ElementName=HostElementName}"/>
</i:EventTrigger>
</gint:InteractivityItems.Triggers>
</gint:InteractivityItems>
</gint:InteractivityTemplate>
</Setter.Value>
</Setter>
</Style>
и это
public void TextBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
TextBox tb = e.Source as TextBox;
if((tb != null) && (tb.IsKeyboardFocusWithin == false))
{
tb.Focus();
e.Handled = true;
}
}
В моем случае, у меня есть пользовательский элемент управления, в котором находятся текстовые поля с выделенным кодом. Код позади имеет функцию обработчика. Я дал своему пользовательскому элементу управления имя в xaml, и я использую это имя для элемента. Это прекрасно работает для меня. Просто примените стиль к любому текстовому полю, где вы хотели бы, чтобы весь текст выделялся при щелчке в текстовом поле.
Первый CallMethodAction вызывает функцию SelectAll текстового поля, когда срабатывает событие GotKeyboardFocus в текстовом поле.
Надеюсь, это поможет.
Для тех, кто интересуется подходом Donnelle/Groky, но нужно щелкнуть справа от последнего символа (но все еще внутри TextBox), чтобы поместить каретку в конец введенного текста, я придумал это решение
int GetRoundedCharacterIndexFromPoint(TextBox textBox, Point clickedPoint)
{
int position = textBox.GetCharacterIndexFromPoint(clickedPoint, true);
// Check if the clicked point is actually closer to the next character
// or if it exceeds the righmost character in the textbox
// (in this case return increase the position by 1)
Rect charLeftEdge = textBox.GetRectFromCharacterIndex(position, false);
Rect charRightEdge = textBox.GetRectFromCharacterIndex(position, true);
double charWidth = charRightEdge.X - charLeftEdge.X;
if (clickedPoint.X + charWidth / 2 > charLeftEdge.X + charWidth) position++;
return position;
}
void SelectivelyIgnoreMouseButton(object sender, MouseButtonEventArgs e)
{
// Find the TextBox
DependencyObject parent = e.OriginalSource as UIElement;
while (parent != null && !(parent is TextBox))
parent = VisualTreeHelper.GetParent(parent);
if (parent != null)
{
var textBox = (TextBox)parent;
if (!textBox.IsKeyboardFocusWithin)
{
// If the text box is not yet focused, give it the focus and
// stop further processing of this click event.
textBox.Focus();
e.Handled = true;
}
else
{
int pos = GetRoundedCharacterIndexFromPoint(textBox, e.GetPosition(textBox));
textBox.CaretIndex = pos;
}
}
}
void SelectAllText(object sender, RoutedEventArgs e)
{
var textBox = e.OriginalSource as TextBox;
if (textBox != null)
textBox.SelectAll();
}
Метод GetRoundedCharacterIndexFromPoint был взят из этой почты.
#region TextBoxIDCard selection
private bool textBoxIDCardGotFocus = false;
private void TextBoxIDCard_GotFocus(object sender, RoutedEventArgs e)
{
this.TextBoxIDCard.SelectAll();
}
private void TextBoxIDCard_LostFocus(object sender, RoutedEventArgs e)
{
textBoxIDCardGotFocus = false;
}
private void TextBoxIDCard_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (textBoxIDCardGotFocus == false)
{
e.Handled = true;
this.TextBoxIDCard.Focus();
textBoxIDCardGotFocus = true;
}
}
#endregion
Попробуйте использовать этот метод расширения для добавления желаемого поведения в любой элемент управления TextBox. Я еще не тестировал его, но, похоже, он удовлетворяет мои потребности.
public static class TextBoxExtensions
{
public static void SetupSelectAllOnGotFocus(this TextBox source)
{
source.GotFocus += SelectAll;
source.PreviewMouseLeftButtonDown += SelectivelyIgnoreMouseButton;
}
private static void SelectAll(object sender, RoutedEventArgs e)
{
var textBox = e.OriginalSource as TextBox;
if (textBox != null)
textBox.SelectAll();
}
private static void SelectivelyIgnoreMouseButton(object sender, MouseButtonEventArgs e)
{
var textBox = (sender as TextBox);
if (textBox != null)
{
if (!textBox.IsKeyboardFocusWithin)
{
e.Handled = true;
textBox.Focus();
}
}
}
}
У меня была такая же проблема. В VB.Net это так просто работает:
VB XAML:
<TextBox x:Name="txtFilterFrequency" />
Codehind:
Private Sub txtFilterText_GotFocus(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles txtFilterText.GotFocus
Me.Dispatcher.BeginInvoke(Sub()
txtFilterText.SelectAll()
End Sub, DispatcherPriority.ApplicationIdle, Nothing)
End Sub
С# (спасибо ViRuSTriNiTy)
private delegate void TextBoxSelectAllDelegate(object sender);
private void TextBoxSelectAll(object sender)
{
(sender as System.Windows.Controls.TextBox).SelectAll();
}
private void MyTextBox_GotFocus(object sender, System.Windows.RoutedEventArgs e)
{
TextBoxSelectAllDelegate d = TextBoxSelectAll;
this.Dispatcher.BeginInvoke(d,
System.Windows.Threading.DispatcherPriority.ApplicationIdle, sender);
}
Я много искал для решения, я нашел пару решений для выбора. Но проблема в том, что мы делаем правый щелчок и делаем вырезание/копирование после выбора части текста из текстового поля, он выбирает все, даже я выбрал часть текст. Исправить это можно здесь. Просто добавьте приведенный ниже код в событие выбора клавиатуры. Это сработало для меня.
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();
}
Я использовал ответ Нильса, но преобразован в более гибкий.
public enum SelectAllMode
{
/// <summary>
/// On first focus, it selects all then leave off textbox and doesn't check again
/// </summary>
OnFirstFocusThenLeaveOff = 0,
/// <summary>
/// On first focus, it selects all then never selects
/// </summary>
OnFirstFocusThenNever = 1,
/// <summary>
/// Selects all on every focus
/// </summary>
OnEveryFocus = 2,
/// <summary>
/// Never selects text (WPF default attitude)
/// </summary>
Never = 4,
}
public partial class TextBox : DependencyObject
{
public static readonly DependencyProperty SelectAllModeProperty = DependencyProperty.RegisterAttached(
"SelectAllMode",
typeof(SelectAllMode?),
typeof(TextBox),
new PropertyMetadata(SelectAllModePropertyChanged));
private static void SelectAllModePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is System.Windows.Controls.TextBox)
{
var textBox = d as System.Windows.Controls.TextBox;
if (e.NewValue != null)
{
textBox.GotKeyboardFocus += OnKeyboardFocusSelectText;
textBox.PreviewMouseLeftButtonDown += OnMouseLeftButtonDown;
}
else
{
textBox.GotKeyboardFocus -= OnKeyboardFocusSelectText;
textBox.PreviewMouseLeftButtonDown -= OnMouseLeftButtonDown;
}
}
}
private static void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DependencyObject dependencyObject = GetParentFromVisualTree(e.OriginalSource);
if (dependencyObject == null)
return;
var textBox = (System.Windows.Controls.TextBox)dependencyObject;
if (!textBox.IsKeyboardFocusWithin)
{
textBox.Focus();
e.Handled = true;
}
}
private static DependencyObject GetParentFromVisualTree(object source)
{
DependencyObject parent = source as UIElement;
while (parent != null && !(parent is System.Windows.Controls.TextBox))
{
parent = VisualTreeHelper.GetParent(parent);
}
return parent;
}
private static void OnKeyboardFocusSelectText(object sender, KeyboardFocusChangedEventArgs e)
{
var textBox = e.OriginalSource as System.Windows.Controls.TextBox;
if (textBox == null) return;
var selectAllMode = GetSelectAllMode(textBox);
if (selectAllMode == SelectAllMode.Never)
{
textBox.SelectionStart = 0;
textBox.SelectionLength = 0;
}
else
textBox.SelectAll();
if (selectAllMode == SelectAllMode.OnFirstFocusThenNever)
SetSelectAllMode(textBox, SelectAllMode.Never);
else if (selectAllMode == SelectAllMode.OnFirstFocusThenLeaveOff)
SetSelectAllMode(textBox, null);
}
[AttachedPropertyBrowsableForChildrenAttribute(IncludeDescendants = false)]
[AttachedPropertyBrowsableForType(typeof(System.Windows.Controls.TextBox))]
public static SelectAllMode? GetSelectAllMode(DependencyObject @object)
{
return (SelectAllMode)@object.GetValue(SelectAllModeProperty);
}
public static void SetSelectAllMode(DependencyObject @object, SelectAllMode? value)
{
@object.SetValue(SelectAllModeProperty, value);
}
}
В XAML вы можете использовать как один из них:
<!-- On first focus, it selects all then leave off textbox and doesn't check again -->
<TextBox attprop:TextBox.SelectAllMode="OnFirstFocusThenLeaveOff" />
<!-- On first focus, it selects all then never selects -->
<TextBox attprop:TextBox.SelectAllMode="OnFirstFocusThenNever" />
<!-- Selects all on every focus -->
<TextBox attprop:TextBox.SelectAllMode="OnEveryFocus" />
<!-- Never selects text (WPF default attitude) -->
<TextBox attprop:TextBox.SelectAllMode="Never" />
Это, безусловно, самое простое решение.
Добавить глобальный обработчик в приложение (App.xaml.cs) и готово. Вам понадобится всего несколько строк кода.
protected override void OnStartup(StartupEventArgs e)
{
EventManager.RegisterClassHandler(typeof(TextBox),
TextBox.GotFocusEvent,
new RoutedEventHandler(TextBox_GotFocus));
base.OnStartup(e);
}
Поэтому используйте класс EventManager, чтобы зарегистрировать глобальный обработчик события для типа (TextBox). Фактический обработчик очень прост:
private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
(sender as TextBox).SelectAll();
}
Проверьте здесь: WPF TextBox SelectAll on Focus
Надеюсь, поможет.
Вот версия ответа на С#, опубликованная @Nasenbaer
private delegate void TextBoxSelectAllDelegate(object sender);
private void TextBoxSelectAll(object sender)
{
(sender as System.Windows.Controls.TextBox).SelectAll();
}
private void MyTextBox_GotFocus(object sender, System.Windows.RoutedEventArgs e)
{
TextBoxSelectAllDelegate d = TextBoxSelectAll;
this.Dispatcher.BeginInvoke(d,
System.Windows.Threading.DispatcherPriority.ApplicationIdle, sender);
}
тогда как MyTextBox_GotFocus
- это обработчик события, назначенный событию GotFocus
MyTextBox
.
Кажется, это хорошо работает для меня. Это в основном резюме некоторых ранних сообщений. Я просто поместил это в свой файл MainWindow.xaml.cs в конструкторе. Я создаю два обработчика, один для клавиатуры и один для мыши, и вставляю оба события в одну и ту же функцию, HandleGotFocusEvent
, которая определяется сразу после конструктора в том же файле.
public MainWindow()
{
InitializeComponent();
EventManager.RegisterClassHandler(typeof(TextBox),
UIElement.GotKeyboardFocusEvent,
new RoutedEventHandler(HandleGotFocusEvent), true);
EventManager.RegisterClassHandler(typeof(TextBox),
UIElement.GotMouseCaptureEvent,
new RoutedEventHandler(HandleGotFocusEvent), true);
}
private void HandleGotFocusEvent(object sender, RoutedEventArgs e)
{
if (sender is TextBox)
(sender as TextBox).SelectAll();
}
Простой способ переопределить mouseDown и выбрать все после doubleclick:
public class DoubleClickTextBox: TextBox
{
public override void EndInit()
{
base.EndInit();
}
protected override void OnMouseEnter(System.Windows.Input.MouseEventArgs e)
{
base.OnMouseEnter(e);
this.Cursor = Cursors.Arrow;
}
protected override void OnMouseDown(System.Windows.Input.MouseButtonEventArgs e)
{
}
protected override void OnMouseDoubleClick(System.Windows.Input.MouseButtonEventArgs e)
{
base.OnMouseDown(e);
this.SelectAll();
}
}
Попробуйте поместить это в конструктор любого элемента управления, где находится ваше текстовое поле:
Loaded += (sender, e) =>
{
MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
myTextBox.SelectAll();
}
Сергей.
После поиска и тестирования я нашел простое решение, которое сработало для меня.
Вам нужно добавить обработчик события в "Загруженное" событие окна вашего контейнера:
private void yourwindow_Loaded(object sender, RoutedEventArgs e)
{
EventManager.RegisterClassHandler(typeof(TextBox),
TextBox.PreviewMouseLeftButtonDownEvent,
new RoutedEventHandler(SelectivelyIgnoreMouseButton));
}
Затем вам нужно создать обработчик в указанном RoutedEventHandler в предыдущем коде:
private void SelectivelyIgnoreMouseButton(object sender, RoutedEventArgs e)
{
TextBox tb = (sender as TextBox);
if (tb != null)
{
if (!tb.IsKeyboardFocusWithin)
{
e.Handled = true;
tb.Focus();
}
}
}
Теперь вы можете добавить команду SelectAll() в обработчики событий GotFocus к любым элементам управления TextBox отдельно:
private void myTextBox_GotFocus(object sender, RoutedEventArgs e)
{
(sender as TextBox).SelectAll();
}
Теперь ваш текст выбран в фокусе!
Адаптировано из Dr. WPF, форумы MSDN
Я тестировал все из них, но только следующее:
protected override void OnStartup(StartupEventArgs e)
{
EventManager.RegisterClassHandler(typeof(TextBox), UIElement.PreviewMouseLeftButtonDownEvent,
new MouseButtonEventHandler(SelectivelyHandleMouseButton), true);
EventManager.RegisterClassHandler(typeof(TextBox), UIElement.GotKeyboardFocusEvent,
new RoutedEventHandler(SelectAllText), true);
EventManager.RegisterClassHandler(typeof(TextBox), UIElement.GotFocusEvent,
new RoutedEventHandler(GotFocus), true);
}
private static void SelectivelyHandleMouseButton(object sender, MouseButtonEventArgs e)
{
var textbox = (sender as TextBox);
if (textbox != null)
{
int hc = textbox.GetHashCode();
if (hc == LastHashCode)
{
if (e.OriginalSource.GetType().Name == "TextBoxView")
{
e.Handled = true;
textbox.Focus();
LastHashCode = -1;
}
}
}
if (textbox != null) textbox.Focus();
}
private static void SelectAllText(object sender, RoutedEventArgs e)
{
var textBox = e.OriginalSource as TextBox;
if (textBox != null)
textBox.SelectAll();
}
private static int LastHashCode;
private static void GotFocus(object sender, RoutedEventArgs e)
{
var textBox = e.OriginalSource as TextBox;
if (textBox != null)
LastHashCode = textBox.GetHashCode();
}
WOW! Прочитав все вышеизложенное, я оказался переполненным и смущенным. Я взял то, что, как я думал, узнал в этом посте, и попробовал что-то совершенно другое. Чтобы выбрать текст в текстовом поле, когда он получает фокус, я использую это:
private void TextField_GotFocus(object sender, RoutedEventArgs e)
{
TextBox tb = (sender as Textbox);
if(tb != null)
{
e.Handled = true;
tb.Focus();
tb.SelectAll();
}
}
Задайте для этого метода свойство GotFocus текстового поля.
Запуск приложения и однократное нажатие в текстовом поле выделяет все, что уже есть в текстовом поле.
Если действительно, целью является выбор текста при щелчке пользователем в текстовом поле, это кажется простым и включает в себя гораздо меньше кода. Просто говорю...