如果我从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.


当前回答

一个简单的方法来覆盖鼠标向下和选择所有双击后:

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();
    }
}

其他回答

这个简单的实现非常适合我:

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;
    }
}

把它应用到所有的文本框,把下面的代码InitializeComponent();

EventManager.RegisterClassHandler(typeof(TextBox), TextBox.GotFocusEvent, new RoutedEventHandler(TextBox_GotFocus));
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.PreviewMouseDownEvent, new MouseButtonEventHandler(TextBox_PreviewMouseDown));

在谷歌搜索和测试之后,我找到了一个简单的解决方案。

你需要在容器窗口的Loaded事件中添加一个事件处理程序:

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();
        }
    }
}

现在,你可以单独将GotFocus事件处理程序上的SelectAll()命令添加到任何TextBox控件:

private void myTextBox_GotFocus(object sender, RoutedEventArgs e)
{
    (sender as TextBox).SelectAll();
}

您的文本现在被选中对焦!

改编自博士WPF解决方案,MSDN论坛

Donnelle的答案是最好的,但是必须派生一个新的类来使用它是一种痛苦。

我没有这样做,而是在App.xaml.cs中为应用程序中的所有文本框注册处理程序。这允许我使用一个标准的文本框控件唐纳利的答案。

在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();
    }
}

不知道为什么它在GotFocus事件中失去了选择。

但是一个解决方案是在GotKeyboardFocus和GotMouseCapture事件上进行选择。这样它就能一直工作。

——编辑——

在这里添加一个例子来告诉人们如何解决上面提到的一些缺点:

private void TextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    // Fixes issue when clicking cut/copy/paste in context menu
    if (textBox.SelectionLength == 0) 
        textBox.SelectAll();
}

private void TextBox_LostMouseCapture(object sender, MouseEventArgs e)
{
    // If user highlights some text, don't override it
    if (textBox.SelectionLength == 0) 
        textBox.SelectAll();

    // further clicks will not select all
    textBox.LostMouseCapture -= TextBox_LostMouseCapture; 
}

private void TextBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    // once we've left the TextBox, return the select all behavior
    textBox.LostMouseCapture += TextBox_LostMouseCapture;
}

这对我来说似乎很有效。它基本上是一些早期帖子的重述。我只是把它放到构造函数的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();
}