如果我从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.
对于那些对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方法取自这篇文章。
我也有同样的问题。在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
c#(感谢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);
}
我使用了Nils的答案,但将其转换为更灵活的答案。
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's 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's default attitude) -->
<TextBox attprop:TextBox.SelectAllMode="Never" />