WPF的TextBox获得焦点时自动全部选择已有内容的方法

您所在的位置:网站首页 鼠标双击不能全选 WPF的TextBox获得焦点时自动全部选择已有内容的方法

WPF的TextBox获得焦点时自动全部选择已有内容的方法

2024-07-14 16:58| 来源: 网络整理| 查看: 265

TextBox元素获得焦点时,可以用SelectAll()来选择已有文字,但不能直接用SelectAll()就得到想要的效果。其中一种方式是通过PreviewMouseDown\GotFocus\LostFocus的多个事件来完成,逻辑有些繁琐。每次都写这些就造成代码重复,因此我写了一个附加属性类来解决这个问题。

本文利用创建的WPF附加属性来获得该功能:即在Text获得焦点的时候,全部选择textbox中已经存在的内容。

/// /// 当 TextBoxBase获得焦点的时候,自动全部选择文字。附加属性为SelectAllWhenGotFocus,类型为bool. /// public class TextBoxAutoSelectHelper { public static readonly DependencyProperty SelectAllWhenGotFocusProperty =DependencyProperty.RegisterAttached("SelectAllWhenGotFocus", typeof(bool), typeof(TextBoxAutoSelectHelper), new FrameworkPropertyMetadata((bool)false,new PropertyChangedCallback(OnSelectAllWhenGotFocusChanged))); public static bool GetSelectAllWhenGotFocus(TextBoxBase d) { return (bool)d.GetValue(SelectAllWhenGotFocusProperty); } public static void SetSelectAllWhenGotFocus(TextBoxBase d, bool value) { d.SetValue(SelectAllWhenGotFocusProperty, value); } private static void OnSelectAllWhenGotFocusChanged(DependencyObject dependency, DependencyPropertyChangedEventArgs e) { if (dependency is TextBoxBase tBox) { var isSelectedAllWhenGotFocus = (bool)e.NewValue; if (isSelectedAllWhenGotFocus) { tBox.PreviewMouseDown += TextBoxPreviewMouseDown; tBox.GotFocus += TextBoxOnGotFocus; tBox.LostFocus += TextBoxOnLostFocus; } else { tBox.PreviewMouseDown -= TextBoxPreviewMouseDown; tBox.GotFocus -= TextBoxOnGotFocus; tBox.LostFocus -= TextBoxOnLostFocus; } } } private static void TextBoxOnGotFocus(object sender, RoutedEventArgs e) { if (sender is TextBoxBase tBox) { tBox.SelectAll(); tBox.PreviewMouseDown -= TextBoxPreviewMouseDown; } } private static void TextBoxPreviewMouseDown(object sender, MouseButtonEventArgs e) { if (sender is TextBoxBase tBox) { tBox.Focus(); e.Handled = true; } } private static void TextBoxOnLostFocus(object sender, RoutedEventArgs e) { if (sender is TextBoxBase tBox) { tBox.PreviewMouseDown += TextBoxPreviewMouseDown; } } }

使用方法如下:

(1)使用Style,以下是直接放在元素中的,更直接的放在窗口的资源中,或资源字典中

                                                                      < Setter Property="local:TextBoxAutoSelectHelper.SelectAllWhenGotFocus" Value="True"/>                                              

(2)或者直接使用元素的附加属性

 

---->以上两种使用方法中的local都是代表命名空间的,具体根据实际情况即可。

补充: (1)对于TextBox,如果之间没有获得焦点,然后要通过鼠标单击来获得焦点,其处理过程表现为:鼠标单击TextBox时,会首先产生PreviewMouseDown事件,处理完PreviewMouseDown事件后,TextBox会获得焦点并进一步产生GotFocus事件。如果在PreviewMouseDown中禁止掉事件进一步传播(e.Handle=true),那么TextBox就不会获得焦点,也不会激发GotFocus事件及其它后续事件。 (2)TextBox的先后产生的与鼠标点击有关的事件包括:PreviewMouseDown,GotFocus,PreviewMouseUp,MouseUp;对于我们想象中应该产生的MouseDown事件,测试过程中无论怎么做都没有激发MouseDown事件。建议尽量不使用PreviewMouseUp和MouseUp事件,其原因如下第(3)和第(4)条所示。 (3)对于TextBox的PreviewMouseUp事件,不建议使用,可能时BUG还是怎么回事。用了以后,整个界面点击任何位置,都只响应该TextBox的事件,其它事件都无法响应了。及时点击关闭窗口的按钮,也是仅仅响应该TextBox的事件,窗口都关闭不了。个人认为是Bug,不知道理解是否正确。 (4)对于TextBox的MouseUp事件,在测试过程中,有时是正常激发的,有时必须要点击TextBox的边框附近才会激发,而点击TextBox的内部不会激发。下图是官方文档中关于Mouse事件的说明:

(5)对于直接使用GotFocus事件来SelectAll()之所以不成功,个人理解是因为:在PreviewMouseDown事件传输过程中,TextBox先获得了焦点,并激发GotFocus事件。然后PreviewMouseDown会进一步向内传输,在此过程中TextBox还会进一步处理鼠标位置信息,并设置光标位置。正因为设置了光标的位置,这又会导致已经选择的文本被取消选择了。所以,为了获得自动选择文字的功能,就在PreviewMouseDown中主动SetFocus(注:这回激发GotFocus事件,在事件处理方法中SelectAll()),并禁止PreviewMouseDown事件进一步向TextBox的更深层次元素传播(e.Handled=true)。

(以上一些结论是根据现象推理的,由于水平有限,如有不准确,还请读者见谅)

 

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3