如果我SelectAll
从GotFocus
事件处理程序调用它,它对鼠标不起作用 - 一旦释放鼠标,选择就会消失.
编辑:人们都喜欢Donnelle的回答,我会试着解释为什么我不喜欢它和接受的答案一样多.
它更复杂,而接受的答案以更简单的方式做同样的事情.
接受答案的可用性更好.当您单击文本中间时,释放鼠标时文本将被取消选中,允许您立即开始编辑,如果您仍想选择全部,只需再次按下按钮,这次它将不会在发布时取消选择.按照Donelle的配方,如果我在文本中间单击,我必须单击第二次才能编辑.如果我单击文本中的某个位置而不是文本外部,这很可能意味着我想开始编辑而不是覆盖所有内容.
Donnelle.. 203
我们有它所以第一次点击选择全部,另一次点击进入光标(我们的应用程序设计用于带有笔的平板电脑).
你可能会发现它很有用.
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(); } }
非常感谢你.这非常有效,应该是接受的答案恕我直言.当TextBox通过键盘或鼠标(显然是手写笔)获得焦点时,上面的代码可以正常工作.+1 (9认同)
我在http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/564b5731-af8a-49bf-b297-6d179615819f/看到一个几乎相同的答案,它也有效,但它怎么样? t使用e.OriginalSource,也不爬行可视化树.做这一切有什么好处吗? (4认同)
此解决方案的另一个缺点是当您使用TextBox的"剪切/复制/粘贴"菜单时,选择任何菜单项时将选择整个文本. (2认同)
Grokys.. 154
Donnelle的答案效果最好,但是必须派出一个新课程才能使用它是一种痛苦.
而不是这样做我在App.xaml.cs中为处理程序中的处理程序注册了应用程序中的所有TextBox.这允许我使用标准TextBox控件的Donnelle答案.
将以下方法添加到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(); } }
这是一个非常酷的解决方案,Matt Hamilton在很久以前也在这里描述过:http://madprops.org/blog/wpf-textbox-selectall-on-focus/ (4认同)
"在美国,拼写的拼写更为常见;但是,拼写的拼写有时在英国和加拿大使用,在澳大利亚和新西兰尤为常见." 所以nyah;) (3认同)
谢谢Nate,纠正了,虽然在我的辩护中,我想指出拼写错误是从Donnelle的回答中逐字复制的;) (2认同)
Nils.. 72
这是相当古老的,但无论如何我都会展示我的答案.
我选择了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); } } }
对于我的"一般但不总是"特征,我在(全局)TextBox-Style中将此属性设置为True.这种方式"选择文本"总是"打开",但我可以在每个文本框的基础上禁用它.
我们有它所以第一次点击选择全部,另一次点击进入光标(我们的应用程序设计用于带有笔的平板电脑).
你可能会发现它很有用.
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中为处理程序中的处理程序注册了应用程序中的所有TextBox.这允许我使用标准TextBox控件的Donnelle答案.
将以下方法添加到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); } } }
对于我的"一般但不总是"特征,我在(全局)TextBox-Style中将此属性设置为True.这种方式"选择文本"总是"打开",但我可以在每个文本框的基础上禁用它.
不知道为什么它在GotFocus事件中失去了选择.
但一种解决方案是在GotKeyboardFocus和GotMouseCapture事件上进行选择.这样它总能奏效.
以下是实现答案解决方案的Blend行为,以方便您:
一个用于附加到单个TextBox:
public class SelectAllTextOnFocusBehavior : Behavior{ 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'es的容器的根目录:
public class SelectAllTextOnFocusMultiBehavior : Behavior{ 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(); } }
虽然这是一个老问题,但我刚刚遇到了这个问题但是使用附加行为来解决它,而不是谢尔盖的答案中的表达行为.这意味着我不需要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中使用它,如下所示:
我在这里写博客.
这是MSDN上一个非常好的非常简单的解决方案:
这是背后的代码:
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(); } } }
我认为这很有效:
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的问题没有直接关系,因为它演示了使用Dispatcher处理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文本框.例如,尝试单击文本框的最后一个字符和文本框右侧之间的空白区域.这里的大多数解决方案将始终选择整个内容,这使得将文本附加到文本框非常困难.
我在这里提出的答案在这方面表现得更好.这是一种行为(因此它需要Blend SDK中的System.Windows.Interactivity程序集).它也可以使用附加属性重写.
public sealed class SelectAllTextOnFocusBehavior : Behavior{ 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; } }
这基于我在这里找到的代码.