如果我从GotFocus事件处理程序中调用SelectAll,它对鼠标不起作用——鼠标一释放,选择就消失了。
编辑:人们喜欢唐纳利的回答,我将试着解释为什么我不像公认的答案那样喜欢它。
It is more complex, while the accepted answer does the same thing in a simpler way.
The usability of accepted answer is better. When you click in the middle of the text, text gets unselected when you release the mouse allowing you to start editing instantly, and if you still want to select all, just press the button again and this time it will not unselect on release. Following Donelle's recipe, if I click in the middle of text, I have to click second time to be able to edit. If I click somewhere within the text versus outside of the text, this most probably means I want to start editing instead of overwriting everything.
哇!读完以上所有内容后,我发现自己不知所措。我从这篇文章中学到了一些东西,并尝试了一些完全不同的东西。当文本框获得焦点时,我使用这个来选择文本:
private void TextField_GotFocus(object sender, RoutedEventArgs e)
{
TextBox tb = (sender as Textbox);
if(tb != null)
{
e.Handled = true;
tb.Focus();
tb.SelectAll();
}
}
将文本框的GotFocus属性设置为该方法。
运行应用程序并在文本框中单击一次,将突出显示文本框中已经存在的所有内容。
如果目标确实是在用户单击文本框时选择文本,这看起来很简单,涉及的代码也少了很多。只是说……
我对此有一个稍微简化的答案(只有PreviewMouseLeftButtonDown事件),这似乎模仿了浏览器的常用功能:
在XAML中,你有一个文本框说:
<TextBox Text="http://www.blabla.com" BorderThickness="2" BorderBrush="Green" VerticalAlignment="Center" Height="25"
PreviewMouseLeftButtonDown="SelectAll" />
在后台代码:
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();
}
}
我已经测试了所有的,但只有以下工作:
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();
}
我认为这很有效:
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);
}
对于那些对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方法取自这篇文章。
这是迄今为止我找到的最直接的解决方案。
您将只需要几行代码。
向应用程序添加全局处理程序(App.xaml.cs)。
使用EventManager类针对一个类型(在本例中为TextBox)注册一个全局事件处理程序。
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();
}
查看这里:WPF文本框选择焦点
我希望这能有所帮助。