Làm cách nào để tự động chọn tất cả văn bản tập trung trong WPF TextBox?


232

Nếu tôi gọi SelectAlltừ một bộ GotFocusxử lý sự kiện, nó không hoạt động với chuột - lựa chọn sẽ biến mất ngay sau khi chuột được phát hành.

EDIT: Mọi người thích câu trả lời của Donnelle, tôi sẽ cố gắng giải thích tại sao tôi không thích nó nhiều như câu trả lời được chấp nhận.

  • Nó phức tạp hơn, trong khi câu trả lời được chấp nhận thực hiện điều tương tự theo cách đơn giản hơn.
  • Khả năng sử dụng của câu trả lời được chấp nhận là tốt hơn. Khi bạn nhấp vào giữa văn bản, văn bản sẽ không được chọn khi bạn nhả chuột cho phép bạn bắt đầu chỉnh sửa ngay lập tức và nếu bạn vẫn muốn chọn tất cả, chỉ cần nhấn lại nút và lần này nó sẽ không bỏ chọn khi phát hành. Theo công thức của Donelle, nếu tôi nhấp vào giữa văn bản, tôi phải nhấp lần thứ hai để có thể chỉnh sửa. Nếu tôi nhấp vào đâu đó trong văn bản so với bên ngoài văn bản, điều này có lẽ có nghĩa là tôi muốn bắt đầu chỉnh sửa thay vì ghi đè lên mọi thứ.

Nếu bạn sẽ có nhiều hơn một hình thức, câu trả lời của cô ấy tiếp tục trở nên ít phức tạp hơn so với hình thức đầu tiên. Khả năng sử dụng của cả hai tùy chọn là không cần thiết vì bạn có thể thay đổi cách chúng hoạt động.
thepaulpage

1
@Sergey: Bạn có thể muốn thay đổi câu trả lời được chấp nhận cho câu hỏi này, vì đã có câu trả lời tốt hơn kể từ đó. Tôi sẽ không đề xuất của tôi, nhưng bạn có thể;)
Grokys

Câu hỏi có thẻ Silverlight, nhưng Silverlight không có hầu hết các sự kiện / bất kỳ loại sự kiện xem trước nào cả. Giải pháp nào nên được sử dụng cho Silverlight sau đó?
Valentin Kuzub

Liên kết "Tại sao sự tập trung trong WPF lại khó khăn như vậy?" bị hỏng
Tối đa

1
như đã đề cập trong một nhận xét về stackoverflow.com/a/2553297/492 bên dưới, madprops.org/blog/wpf-textbox-selectall-on-f Focus là một giải pháp dễ dàng và duy trì hành vi của nouse ban đầu. Tôi đặt đăng ký sự kiện trong hàm tạo vì tôi chỉ có một điều khiển WPF trong ứng dụng.
CAD bloke

Câu trả lời:


75

Không biết tại sao nó mất lựa chọn trong GotFocussự kiện.

Nhưng một giải pháp là thực hiện lựa chọn trên GotKeyboardFocusvà các GotMouseCapturesự kiện. Bằng cách đó, nó sẽ luôn hoạt động.


10
Không. Khi nhấp chuột vào giữa văn bản hiện có - lựa chọn sẽ bị mất ngay khi nút chuột được phát hành.
Serge Aldoukhov

3
Mặc dù - sau một lần nhấp thứ hai, nó sẽ chọn lại tất cả văn bản ... Không chắc đó có phải là hành vi dự định từ các nhà thiết kế WPF hay không, nhưng khả năng sử dụng không phải là xấu. Một điểm khác biệt so với một trình xử lý GotF Focus duy nhất là nhấp vào một khoảng trống trong TextBox sẽ chọn tất cả.
Serge Aldoukhov

3
Đây cũng là giải pháp nắm tay của tôi. Nhưng tôi thấy rằng người dùng thực sự khó chịu, khi họ không thể chọn Văn bản bằng Chuột, bởi vì mỗi lần họ nhấp vào toàn bộ văn bản sẽ được chọn ...
Nils

1
Một nhược điểm nữa của giải pháp này là khi bạn sử dụng menu "Cắt / Sao chép / Dán" của TextBox, toàn bộ văn bản được chọn khi bạn chọn bất kỳ mục menu nào.

@gcores Tôi biết cái này đã cũ, nhưng có ai biết tại sao trong sự kiện GotF Focus, văn bản được chọn bị mất không? Tuy nhiên, bạn đúng về việc nó hoạt động trong các sự kiện khác và đó là một giải pháp hoàn toàn chấp nhận được trong cuốn sách của tôi.
bại

210

Chúng tôi có nó để lần nhấp đầu tiên chọn tất cả và lần nhấp khác chuyển đến con trỏ (ứng dụng của chúng tôi được thiết kế để sử dụng trên máy tính bảng có bút).

Bạn có thể thấy nó hữu ích.

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

9
Cảm ơn bạn rất nhiều cho việc này. Điều này làm việc tuyệt vời và nên được IMHO trả lời. Đoạn mã trên hoạt động khi TextBox nhận được tiêu điểm thông qua bàn phím hoặc chuột (và rõ ràng là bút stylus). +1
Noakes

5
Tôi đã thấy một câu trả lời gần như giống hệt ở đây social.msdn.microsoft.com/Forums/en-US/wpf/thread/ , nó hoạt động tốt như thế nào, bao giờ nó không sử dụng e.OrigenSource, cũng không bò qua cây trực quan. Có bất kỳ lợi thế để làm tất cả điều này?
Marco Luglio

1
Hoạt động tuyệt vời, nhưng sẽ hoàn hảo nếu nó vẫn cho phép lựa chọn kéo văn bản bằng chuột. Thanh địa chỉ Google Chrome là một ví dụ hoàn hảo về hệ thống lý tưởng: nếu người dùng nhấp và phát hành mà không kéo, toàn bộ văn bản được tô sáng. Tuy nhiên, nếu người dùng nhấp và kéo, kéo sẽ chọn văn bản bình thường mà không chọn tất cả. Chọn tất cả chỉ xảy ra khi phát hành chuột . Tôi sẽ mân mê và xem liệu tôi có thể cải thiện thiết kế này không.
devios1

2
Một nhược điểm nữa của giải pháp này là khi bạn sử dụng menu "Cắt / Sao chép / Dán" của TextBox, toàn bộ văn bản được chọn khi bạn chọn bất kỳ mục menu nào.

1
Tôi thấy rằng một thử nghiệm bổ sung trong SelectAllTextphương pháp textBox.IsFocusedcải thiện nó. Bạn không muốn chọn tất cả khi đó GetKeyboardFocuslà do tab alt vào chương trình.
Scott Stafford

164

Câu trả lời của Donnelle hoạt động tốt nhất, nhưng phải tìm ra một lớp mới để sử dụng nó là một nỗi đau.

Thay vì làm điều đó, tôi đăng ký trình xử lý các trình xử lý trong App.xaml.cs cho tất cả các TextBox trong ứng dụng. Điều này cho phép tôi sử dụng câu trả lời của Donnelle với điều khiển TextBox tiêu chuẩn.

Thêm các phương thức sau vào App.xaml.cs của bạn:

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

4
Đây là một giải pháp khá tuyệt vời, nó cũng được Matt Hamilton mô tả từ lâu ở đây: madprops.org/blog/wpf-textbox-selectall-on-f Focus
Ashley Davis

Có một số lỗi sai chính tả trong 'nhận', 'tập trung'
Nate Zaugg

2
Cảm ơn Nate, đã sửa chữa, mặc dù trong phần bảo vệ của tôi, tôi muốn chỉ ra những lỗi chính tả đã được sao chép nguyên văn từ câu trả lời của Donnelle;)
Grokys

Câu hỏi có thẻ Silverlight, nhưng Silverlight không có hầu hết các sự kiện / bất kỳ loại sự kiện xem trước nào cả. Giải pháp nào nên được sử dụng cho Silverlight sau đó? cảm ơn trước
Valentin Kuzub

4
"Việc đánh vần tập trung phổ biến hơn nhiều ở Mỹ, tuy nhiên, cách đánh vần đôi khi được sử dụng ở Anh và Canada, và đặc biệt phổ biến ở Úc và New Zealand." So nyah;)
Donnelle

85

Điều này khá cũ, nhưng dù sao tôi cũng sẽ hiển thị câu trả lời của mình.

Tôi đã chọn một phần câu trả lời của Donnelle (bỏ qua nhấp đúp chuột) vì tôi nghĩ điều này tự nhiên hơn. Tuy nhiên, giống như gcores, tôi không thích phải tạo một lớp dẫn xuất. Nhưng tôi cũng không thích OnStartupphương pháp gcores . Và tôi cần điều này trên cơ sở "nói chung nhưng không phải luôn luôn".

Tôi đã triển khai phần này dưới dạng đính kèm DependencyPropertyđể tôi có thể đặt local:SelectTextOnFocus.Active = "True"trong xaml. Tôi thấy cách này vừa lòng nhất.

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

Đối với tính năng "chung nhưng không phải luôn luôn" của tôi, tôi đặt Thuộc tính Attache này Truethành (toàn cầu)TextBox Style . Cách này "chọn Văn bản" luôn luôn "bật", nhưng tôi có thể vô hiệu hóa nó trên cơ sở mỗi hộp văn bản.


8
+1 điều này tốt hơn nhiều so với việc đặt nó trên toàn cầu và đó là "cách WPF" hơn là xuất phát từ TextBox.
stijn

3
+1 Đồng ý với stijn. "Ẩn" mã của bạn trong app.cs không tốt cho nhà phát triển nghèo, người phải tìm ra lý do tại sao Chọn AllOnF Focus xảy ra. :-) Tôi vừa bỏ cái này vào lớp của tôi cho TextBoxBehaviors và sau đó cập nhật TextBox Style cơ bản của tôi. Làm việc một điều trị. Chúc mừng
Lee Campbell

2
@tronda: Chỉ cần thêm một kiểu vào tài nguyên bằng TargetType của TextBox. Tôi đề nghị bạn nên xem wpftutorial.net/Styles.html
Nils

2
+1 khác cho câu trả lời tốt nhất. Vấn đề duy nhất tôi thấy là văn bản luôn được chọn ngay cả khi tôi sử dụng nút chuột phải - điều tôi thường làm để chỉnh sửa văn bản qua menu ngữ cảnh - giải pháp không hoạt động trong trường hợp này vì nó luôn chọn tất cả văn bản ngay cả khi tôi chỉ muốn cắt 1 từ thông qua menu ngữ cảnh. Các bạn có biết làm thế nào để khắc phục điều này?
dùng3313608

2
Tôi thích câu trả lời này nhưng tại sao bạn phải mở rộng DependencyObject? Tôi loại bỏ nó và nó vẫn hoạt động tốt.
Fred

47

Dưới đây là các hành vi Blend thực hiện giải pháp trả lời để thuận tiện cho bạn:

Một để đính kèm vào một TextBox duy nhất:

public class SelectAllTextOnFocusBehavior : Behavior<TextBox>
{
    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;
        }
    }
}

Và một để đính kèm vào thư mục gốc chứa nhiều TextBox'es:

public class SelectAllTextOnFocusMultiBehavior : Behavior<UIElement>
{
    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();
    }
}

Đây là giải pháp tốt nhất và sạch nhất. Cảm ơn rất nhiều cho việc chia sẻ nó.
Golvellius

Nó trông rất đẹp, nhưng vì một số lý do, nó phá vỡ sự kiểm soát của tab ... Có ai biết tại sao không?
Marc

Tôi muốn sử dụng giải pháp yor. Nhưng thực sự đã mất ... có lẽ bạn có một mẫu?
Juan Pablo Gomez

Khi bạn bấm vào một nơi nào đó trong hộp văn bản trong khi lấy nét (hãy tưởng tượng bạn muốn di chuyển dấu mũ đến một nơi khác), nó sẽ chọn lại All thay vì di chuyển dấu mũ. Thật bất ngờ. Đã sửa lỗi bằng cách thay thế GotMouseCapture bằng MouseDoubleClick, điều này là phổ biến. Nhờ các giải pháp sau từ MSDN.
norekhov

1
Nó dường như không hoạt động khi hộp văn bản nhận được tiêu điểm ban đầu thông qua FocusManager.F FocusedEuity. Bất cứ ý tưởng tại sao?
szx 24/2/2015

24

Mặc dù đây là một câu hỏi cũ, tôi vừa gặp vấn đề này nhưng đã giải quyết nó bằng Hành vi đính kèm, thay vì Hành vi biểu hiện như trong câu trả lời của Serge. Điều này có nghĩa là tôi không cần phụ thuộc vào System.Windows.InteractivitySDK 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();
    }
}

Sau đó, bạn có thể sử dụng nó trong XAML của mình như thế này:

<TextBox Text="Some Text" behaviors:TextBoxBehavior.SelectAllTextOnFocus="True"/>

Tôi viết blog về nó ở đây .


Tôi thích cách tiếp cận này nhưng các phương thức Nhận / Đặt không nên kết thúc bằng "Thuộc tính"; Tôi đã phải loại bỏ điều đó để có được mã biên dịch sau khi thêm phần Xaml.
Patrick Quirk

Rất đẹp, làm việc đúng như mong đợi. Tôi thích điều này vì nó giúp tôi tách biệt các mối quan tâm khi thực hiện MVVM.
Killnine

16

Đây là một giải pháp rất đơn giản rất tốt trên MSDN :

<TextBox
    MouseDoubleClick="SelectAddress"
    GotKeyboardFocus="SelectAddress"
    PreviewMouseLeftButtonDown="SelectivelyIgnoreMouseButton" />

Đây là mã phía sau:

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

1
Về cơ bản, đây là giải pháp tương tự như giải pháp được đánh giá cao nhất trong chủ đề này. Nhưng kể từ khi nó hai năm trước, bây giờ tôi biết nơi từ @Donnelle mượn nó;)
Sergey Aldoukhov

Giải pháp này có vẻ dễ nhất và làm việc cho tôi. Tôi muốn có một tập hợp con cụ thể của văn bản được chọn theo mặc định khi vào hộp văn bản.
Jack B nhanh nhẹn

10

Tôi nghĩ rằng điều này hoạt động tốt:

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

Nếu bạn muốn triển khai nó như một phương thức mở rộng:

public static void SelectAllText(this System.Windows.Controls.TextBox tb)
{
    tb.Dispatcher.BeginInvoke(
        new Action(delegate
        {
            tb.SelectAll();
        }), System.Windows.Threading.DispatcherPriority.Input);
}

Và trong GotFocussự kiện của bạn :

private void ValueText_GotFocus(object sender, RoutedEventArgs e)
{
    TextBox tb = (TextBox)e.OriginalSource;
    tb.SelectAllText();
}

Tôi phát hiện ra giải pháp ở trên vì vài tháng trước tôi đang tìm cách đặt trọng tâm thành một định hướng UIElement. Tôi đã phát hiện ra mã dưới đây ở đâu đó (tín dụng được đưa ra) và nó hoạt động tốt. Tôi đăng nó ngay cả khi nó không liên quan trực tiếp đến câu hỏi của OP vì nó thể hiện cùng một kiểu sử dụng Dispatcherđể làm việc với a 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);
}

Tôi đoán đây là phương pháp đơn giản nhất để thực hiện. sau khi tạo phương thức mở rộng, bạn sẽ chỉ cần gọi myTextBox.SelectAllText (). Tại sao câu trả lời này không nhận được nhiều điểm hơn? Tại sao các giải pháp khác tốt hơn nhiều?
Tôn Nam Nam

2
Tôi sẽ tránh phương pháp này vì nó dựa vào cuộc gọi không đồng bộ để chạy sau trình xử lý MouseUp của hộp văn bản. Tôi sẽ không tin điều này là 100% mang tính quyết định và có thể dẫn đến hành vi không nhất quán. Mặc dù nó có thể không xảy ra, tôi muốn sử dụng các phương pháp chắc chắn ở trên.
Rob H

6

Đây là một nỗ lực để giải quyết một số vấn đề với các giải pháp khác:

  1. Sử dụng menu ngữ cảnh nhấp chuột phải để cắt / sao chép / quá khứ sẽ chọn tất cả văn bản ngay cả khi bạn không chọn tất cả.
  2. Khi trở về từ menu ngữ cảnh nhấp chuột phải, tất cả văn bản luôn được chọn.
  3. Khi trở về ứng dụng có dấu Alt+ Tab, tất cả văn bản luôn được chọn.
  4. Khi cố gắng chỉ chọn một phần văn bản trong lần nhấp đầu tiên, tất cả luôn được chọn (không giống như thanh địa chỉ Google chromes chẳng hạn).

Mã tôi đã viết là cấu hình. Bạn có thể chọn vào những gì hành động chọn tất cả các hành vi xảy ra bằng cách thiết lập ba lĩnh vực readonly: SelectOnKeybourdFocus, SelectOnMouseLeftClick, SelectOnMouseRightClick.

Nhược điểm của giải pháp này là trạng thái tĩnh và phức tạp hơn được lưu trữ. Nó có vẻ như một cuộc đấu tranh xấu xí với hành vi mặc định của TextBoxkiểm soát. Tuy nhiên, nó vẫn hoạt động và tất cả các mã được ẩn trong lớp thùng chứa Thuộc tính đính kèm.

public static class TextBoxExtensions
{
    // Configuration fields to choose on what actions the select all behavior should occur.
    static readonly bool SelectOnKeybourdFocus = true;
    static readonly bool SelectOnMouseLeftClick = true;
    static readonly bool SelectOnMouseRightClick = true;

    // Remembers a right click context menu that is opened 
    static ContextMenu ContextMenu = null;

    // Remembers if the first action on the TextBox is mouse down 
    static bool FirstActionIsMouseDown = false;

    public static readonly DependencyProperty SelectOnFocusProperty =
        DependencyProperty.RegisterAttached("SelectOnFocus", typeof(bool), typeof(TextBoxExtensions), new PropertyMetadata(false, new PropertyChangedCallback(OnSelectOnFocusChanged)));

    [AttachedPropertyBrowsableForChildren(IncludeDescendants = false)]
    [AttachedPropertyBrowsableForType(typeof(TextBox))]
    public static bool GetSelectOnFocus(DependencyObject obj)
    {
        return (bool)obj.GetValue(SelectOnFocusProperty);
    }

    public static void SetSelectOnFocus(DependencyObject obj, bool value)
    {
        obj.SetValue(SelectOnFocusProperty, value);
    }

    private static void OnSelectOnFocusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (!(d is TextBox textBox)) return;

        if (GetSelectOnFocus(textBox))
        {
            // Register events
            textBox.PreviewMouseDown += TextBox_PreviewMouseDown;
            textBox.PreviewMouseUp += TextBox_PreviewMouseUp;
            textBox.GotKeyboardFocus += TextBox_GotKeyboardFocus;
            textBox.LostKeyboardFocus += TextBox_LostKeyboardFocus;
        }
        else
        {
            // Unregister events
            textBox.PreviewMouseDown -= TextBox_PreviewMouseDown;
            textBox.PreviewMouseUp -= TextBox_PreviewMouseUp;
            textBox.GotKeyboardFocus -= TextBox_GotKeyboardFocus;
            textBox.LostKeyboardFocus -= TextBox_LostKeyboardFocus;
        }
    }

    private static void TextBox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        if (!(sender is TextBox textBox)) return;

        // If mouse clicked and focus was not in text box, remember this is the first click.
        // This will enable to prevent select all when the text box gets the keyboard focus 
        // right after the mouse down event.
        if (!textBox.IsKeyboardFocusWithin)
        {
            FirstActionIsMouseDown = true;
        }
    }

    private static void TextBox_PreviewMouseUp(object sender, MouseButtonEventArgs e)
    {
        if (!(sender is TextBox textBox)) return;

        // Select all only if:
        // 1) SelectOnMouseLeftClick/SelectOnMouseRightClick is true and left/right button was clicked
        // 3) This is the first click
        // 4) No text is selected
        if (((SelectOnMouseLeftClick && e.ChangedButton == MouseButton.Left) || 
            (SelectOnMouseRightClick && e.ChangedButton == MouseButton.Right)) &&
            FirstActionIsMouseDown &&
            string.IsNullOrEmpty(textBox.SelectedText))
        {
            textBox.SelectAll();
        }

        // It is not the first click 
        FirstActionIsMouseDown = false;
    }

    private static void TextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
    {
        if (!(sender is TextBox textBox)) return;

        // Select all only if:
        // 1) SelectOnKeybourdFocus is true
        // 2) Focus was not previously out of the application (e.OldFocus != null)
        // 3) The mouse was pressed down for the first after on the text box
        // 4) Focus was not previously in the context menu
        if (SelectOnKeybourdFocus &&
            e.OldFocus != null &&
            !FirstActionIsMouseDown &&
            !IsObjectInObjectTree(e.OldFocus as DependencyObject, ContextMenu))
        {
            textBox.SelectAll();
        }

        // Forget ContextMenu
        ContextMenu = null;
    }

    private static void TextBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
    {
        if (!(sender is TextBox textBox)) return;

        // Remember ContextMenu (if opened)
        ContextMenu = e.NewFocus as ContextMenu;

        // Forget selection when focus is lost if:
        // 1) Focus is still in the application
        // 2) The context menu was not opened
        if (e.NewFocus != null
            && ContextMenu == null)
        {
            textBox.SelectionLength = 0;
        }
    }

    // Helper function to look if a DependencyObject is contained in the visual tree of another object
    private static bool IsObjectInObjectTree(DependencyObject searchInObject, DependencyObject compireToObject)
    {
        while (searchInObject != null && searchInObject != compireToObject)
        {
            searchInObject = VisualTreeHelper.GetParent(searchInObject);
        }

        return searchInObject != null;
    }
}

Để tùy chỉnh Thuộc tính được đính kèm vào a TextBox, tất cả những gì bạn cần làm là thêm không gian tên xml ( xmlns) của Thuộc tính được đính kèm và sau đó sử dụng nó như sau:

<TextBox attachedprop:TextBoxExtensions.SelectOnFocus="True"/>

Một số lưu ý về giải pháp này:

  1. Để ghi đè hành vi mặc định của sự kiện chuột xuống và cho phép chỉ chọn một phần văn bản trong lần nhấp đầu tiên, tất cả văn bản được chọn trong sự kiện chuột lên.
  2. Tôi đã phải đối phó với thực tế là những người còn TextBoxnhớ lựa chọn của nó sau khi nó mất tập trung. Tôi thực sự đã ghi đè hành vi này.
  3. Tôi phải nhớ nếu một nút chuột xuống là hành động đầu tiên trên TextBox( FirstActionIsMouseDowntrường tĩnh).
  4. Tôi phải nhớ menu ngữ cảnh được mở bằng một cú nhấp chuột phải ( ContextMenutrường tĩnh).

Tác dụng phụ duy nhất tôi tìm thấy là khi nào SelectOnMouseRightClicklà đúng. Đôi khi, trình đơn ngữ cảnh nhấp chuột phải nhấp nháy khi mở và nhấp chuột phải vào chỗ trống, TextBoxkhông "chọn tất cả".


5

Tôi không tìm thấy câu trả lời nào được trình bày ở đây bắt chước một hộp văn bản Windows tiêu chuẩn. Chẳng hạn, hãy thử bấm vào khoảng trắng giữa ký tự cuối cùng của hộp văn bản và bên phải của hộp văn bản. Hầu hết các giải pháp ở đây sẽ luôn chọn toàn bộ nội dung, điều này khiến cho việc thêm văn bản vào hộp văn bản rất khó khăn.

Câu trả lời mà tôi trình bày ở đây ứng xử tốt hơn trong khía cạnh này. Đây là một hành vi (vì vậy nó yêu cầu lắp ráp System.Windows.Interactivity từ Blend SDK ). Nó có thể được viết lại bằng cách sử dụng các thuộc tính đính kèm là tốt.

public sealed class SelectAllTextOnFocusBehavior : Behavior<TextBox>
{
    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;
    }
}

Điều này dựa trên mã tôi đã tìm thấy ở đây .


1
Mặc dù đây là một câu trả lời hay, tôi nghĩ rằng khi người dùng nhấp vào khoảng trắng, ý định của anh ta (trong một ứng dụng kinh doanh) có lẽ là ghi đè toàn bộ giá trị, vì vậy chọn tất cả là cách tiếp cận phù hợp.
Serge Aldoukhov

1
Sergey: lần nhấp đầu tiên sẽ chọn toàn bộ giá trị, lần nhấp thứ hai sẽ đặt con trỏ ở bên phải giá trị. Trong các giải pháp được trình bày khác, lần nhấp thứ hai sẽ giữ toàn bộ giá trị được chọn, khiến cho việc gắn vào giá trị rất khó khăn.
Kristof Verbiest

Làm thế nào được sử dụng này? Tôi đã thêm mã này vào App.xaml.cs nhưng dường như nó không có ảnh hưởng đến TextBoxes trong ứng dụng của tôi.
PIntag

5

Việc thực hiện đơn giản này hoạt động hoàn hảo đối với tôi:

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

Để áp dụng nó cho tất cả TextBox, hãy đặt đoạn mã sauInitializeComponent();

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

4

Trong tệp App.xaml:

<Application.Resources>
    <Style TargetType="TextBox">
        <EventSetter Event="GotKeyboardFocus" Handler="TextBox_GotKeyboardFocus"/>
    </Style>
</Application.Resources>

Trong tệp App.xaml.cs:

private void TextBox_GotKeyboardFocus(Object sender, KeyboardFocusChangedEventArgs e)
{
    ((TextBox)sender).SelectAll();
}

Với mã này, bạn đạt được tất cả TextBoxtrong ứng dụng của bạn.


3

Lấy từ đây :

Đăng ký xử lý sự kiện toàn cầu trong tệp App.xaml.cs:

protected override void OnStartup(StartupEventArgs e)
{
    EventManager.RegisterClassHandler(typeof(TextBox),TextBox.GotFocusEvent,
    new RoutedEventHandler(TextBox_GotFocus));

    base.OnStartup(e);
}

Sau đó, xử lý đơn giản như:

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

3

Tôi nhận ra điều này rất cũ, nhưng đây là giải pháp của tôi dựa trên các không gian tên tương tác / biểu thức / microsoft.

Đầu tiên, tôi làm theo các hướng dẫn tại liên kết này để đặt các kích hoạt tương tác thành một kiểu.

Sau đó, nó đi xuống này

<Style x:Key="baseTextBox" TargetType="TextBox">
  <Setter Property="gint:InteractivityItems.Template">
    <Setter.Value>
      <gint:InteractivityTemplate>
        <gint:InteractivityItems>
          <gint:InteractivityItems.Triggers>
            <i:EventTrigger EventName="GotKeyboardFocus">
              <ei:CallMethodAction MethodName="SelectAll"/>
            </i:EventTrigger>
            <i:EventTrigger EventName="PreviewMouseLeftButtonDown">
              <ei:CallMethodAction MethodName="TextBox_PreviewMouseLeftButtonDown"
                TargetObject="{Binding ElementName=HostElementName}"/>
            </i:EventTrigger>
          </gint:InteractivityItems.Triggers>
        </gint:InteractivityItems>
      </gint:InteractivityTemplate>
    </Setter.Value>
  </Setter>
</Style>

và điều này

public void TextBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
  TextBox tb = e.Source as TextBox;
  if((tb != null) && (tb.IsKeyboardFocusWithin == false))
  {
    tb.Focus();
    e.Handled = true;
  }
}

Trong trường hợp của tôi, tôi có một điều khiển người dùng trong đó các hộp văn bản có mã phía sau. Mã phía sau có chức năng xử lý. Tôi đã cho người dùng của mình kiểm soát một tên trong XAML và tôi đang sử dụng tên đó cho thành phần. Điều này đang làm việc hoàn hảo cho tôi. Chỉ cần áp dụng kiểu cho bất kỳ TextBoxnơi nào bạn muốn có tất cả văn bản được chọn khi bạn nhấp vào TextBox.

Đầu tiên CallMethodActiongọi SelectAllphương thức của hộp văn bản khi GotKeyboardFocussự kiện đang TextBoxcháy.

Tôi hi vọng cái này giúp được.


Vì đây là một câu hỏi cũ, nó có thể giúp câu trả lời của bạn được chú ý nếu bạn đề cập đến lý do tại sao ai đó có thể chọn phương pháp này.
divibisan 26/03/18

Trước hết, điều này không cần phải được đặt trong một phong cách, nhưng tôi nghĩ rõ ràng rằng có nhiều điều khiển hộp văn bản cần điều này, một phong cách là cách để đi.
wiyosaya

1
Có thể một số người sẽ không đồng ý với cách tiếp cận này, tuy nhiên, tại sao bạn có thể sử dụng cách tiếp cận này, nó không yêu cầu TextBox phân lớp, đăng ký các sự kiện xử lý lớp, phương thức mở rộng, tạo thuộc tính đính kèm, v.v. vào từ điển tài nguyên của bất kỳ dự án xaml. Nếu không có x: Key, nó sẽ được áp dụng cho bất kỳ trường hợp TextBox nào trong phạm vi của từ điển tài nguyên mà không phải thay đổi xaml của mỗi hộp văn bản riêng lẻ. Trong một số trường hợp, nó có thể là một cách tiếp cận sạch hơn.
wiyosaya

2

Tôi đã sử dụng câu trả lời của Nils nhưng được chuyển đổi thành linh hoạt hơn.

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

Trong XAML, bạn có thể sử dụng như một trong những điều sau:

<!-- 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" />

1
Giải pháp thực sự tốt để sử dụng trong các mẫu vì bạn có thể liên kết nó với xaml mà không cần bất kỳ cơ sở mã thực tế nào, chỉ cần mở rộng hành vi của hộp văn bản.
Eric Johansson

2

Đây là phiên bản C # của câu trả lời được đăng bởi @Nasenbaer

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

trong khi đó MyTextBox_GotFocuslà xử lý sự kiện được gán cho GotFocussự kiện của MyTextBox.


2

Tôi có một câu trả lời hơi đơn giản cho việc này (chỉ với PreviewMouseLeftButtonDownsự kiện) dường như bắt chước chức năng thông thường của trình duyệt:

Trong XAML bạn có TextBoxtiếng nói:

<TextBox Text="http://www.blabla.com" BorderThickness="2" BorderBrush="Green" VerticalAlignment="Center" Height="25"
                 PreviewMouseLeftButtonDown="SelectAll" />

Trong cơ sở mã hóa:

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

1
Có thể muốn thêm một sự kiện GotPalF Focus với TextBox.SelectAll () bên trong cho những người theo cách của họ xung quanh ứng dụng của bạn. Giải pháp của bạn cũng hoạt động với PasswordBoxes (vì PasswordBox là loại kín nên chúng không thể được mở rộng).
David Sherret

1

Hãy thử phương pháp tiện ích mở rộng này để thêm hành vi mong muốn vào bất kỳ điều khiển TextBox nào. Tôi chưa thử nghiệm rộng rãi, nhưng dường như nó đáp ứng nhu cầu của tôi.

public static class TextBoxExtensions
{
    public static void SetupSelectAllOnGotFocus(this TextBox source)
    {
        source.GotFocus += SelectAll;
        source.PreviewMouseLeftButtonDown += SelectivelyIgnoreMouseButton;
    }

    private static void SelectAll(object sender, RoutedEventArgs e)
    {
        var textBox = e.OriginalSource as TextBox;
        if (textBox != null)
            textBox.SelectAll();
    }

    private static void SelectivelyIgnoreMouseButton(object sender, MouseButtonEventArgs e)
    {
        var textBox = (sender as TextBox);
        if (textBox != null)
        {
            if (!textBox.IsKeyboardFocusWithin)
            {
                e.Handled = true;
                textBox.Focus();
            }
        }
    }
}

1

Tôi đã tìm kiếm rất nhiều giải pháp, tôi tìm thấy một vài giải pháp để chọn Nhưng, vấn đề là khi chúng tôi nhấp chuột phải và cắt / sao chép sau khi chọn một phần văn bản từ hộp văn bản, nó chọn tất cả ngay cả tôi đã chọn một phần văn bản. Để khắc phục điều này ở đây là giải pháp. Chỉ cần thêm mã dưới đây trong sự kiện chọn bàn phím. Điều này làm việc cho tôi.

private static void SelectContentsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    if (d is TextBox)
    {
        TextBox textBox = d as TextBox;
        if ((e.NewValue as bool?).GetValueOrDefault(false))
        {
            textBox.GotKeyboardFocus += OnKeyboardFocusSelectText;                 
        }
        else
        {
            textBox.GotKeyboardFocus -= OnKeyboardFocusSelectText;

        }
    }
}


private static void OnKeyboardFocusSelectText(object sender, KeyboardFocusChangedEventArgs e)
{
    if (e.KeyboardDevice.IsKeyDown(Key.Tab))
        ((TextBox)sender).SelectAll();
}

1

Tôi đã có vấn đề tương tự. Trong VB.Net nó hoạt động dễ dàng theo cách đó:

VB XAML:

<TextBox x:Name="txtFilterFrequency" />

Mật mã:

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 # (cảm ơn 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);
}

Giải pháp tốt nhất cho tôi, tôi đã đăng một bản dịch C # tại đây: stackoverflow.com/a/48385409/3936440
ViRuSTriNiTy

Đối với tôi, cách tiếp cận này đôi khi không chọn văn bản. Tôi nghĩ đó là điều kiện cuộc đua do BeginInvoke.
Vimes

Xin hãy chỉ ra cụ thể. Ưu tiên điều phối đang làm việc trên các ứng dụng mặc định như mong đợi. Tình hình của bạn là gì Bạn đã thử chính xác như mô tả? Bất cứ điều gì đặc biệt trong giải pháp của bạn?
Nasenbaer

1

Đây là giải pháp đơn giản nhất.

Thêm một trình xử lý toàn cầu vào ứng dụng (App.xaml.cs) và thực hiện. Bạn sẽ chỉ cần một vài dòng mã.

protected override void OnStartup(StartupEventArgs e)
{
    EventManager.RegisterClassHandler(typeof(TextBox),
        TextBox.GotFocusEvent,
        new RoutedEventHandler(TextBox_GotFocus));

    base.OnStartup(e);
}

Vì vậy, sử dụng lớp EventManager để đăng ký một trình xử lý sự kiện toàn cầu theo một loại (TextBox). Trình xử lý thực tế đã chết đơn giản:

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

Kiểm tra tại đây: WPF TextBox Chọn All on Focus

Hy vọng nó giúp.


1

Đối với những người quan tâm đến cách tiếp cận của Donnelle / Groky, nhưng muốn nhấp vào bên phải của ký tự cuối cùng (nhưng vẫn ở trong TextBox) để đặt dấu mũ ở cuối văn bản đã nhập, tôi đã đưa ra giải pháp này:

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

Các GetRoundedCharacterIndexFromPointphương pháp được lấy từ đây đường bưu điện.


1
Hoạt động tốt, nhưng sự kiện nhấp đúp không được kích hoạt
Rodrigo Caballero

Trên thực tế, nó tham gia vào sự kiện doubleclick nhưng thuộc tính OriginalSource thuộc loại TextBoxView. Vì vậy, phương thức Chọn Tất cả phải như thế này: private static void SelectAllText (người gửi đối tượng, RoutedEventArss e) {var textBox = e.OrigenSource là TextBox; if (textBox! = null) {textBox.Select ALL (); System.Diagnostics.Debug.WriteLine ("Đã chọn TẤT CẢ"); } if if (người gửi là TextBox) {(người gửi dưới dạng TextBox) .Select ALL (); }
Rodrigo Caballero

1

Sau khi googling và thử nghiệm, tôi đã tìm thấy một giải pháp đơn giản phù hợp với mình.

Bạn cần thêm một trình xử lý sự kiện vào Loadedsự kiện của cửa sổ container của bạn:

private void yourwindow_Loaded(object sender, RoutedEventArgs e)
{
    EventManager.RegisterClassHandler(typeof(TextBox),
        TextBox.PreviewMouseLeftButtonDownEvent,
        new RoutedEventHandler(SelectivelyIgnoreMouseButton));
}

Tiếp theo, bạn phải tạo trình xử lý cho tham chiếu RoutedEventHandlertrong mã trước đó:

private void SelectivelyIgnoreMouseButton(object sender, RoutedEventArgs e)
{
    TextBox tb = (sender as TextBox);
    if (tb != null)
    {
        if (!tb.IsKeyboardFocusWithin)
        {
            e.Handled = true;
            tb.Focus();
        }
    }
}

Bây giờ, bạn có thể thêm SelectAll()lệnh trên GotFocustrình xử lý sự kiện vào bất kỳ TextBoxđiều khiển nào một cách riêng biệt:

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

Văn bản của bạn bây giờ được chọn tập trung!

Chuyển thể từ giải pháp của Tiến sĩ WPF, Diễn đàn MSDN


Tôi vừa sử dụng: private async void TBTime_GotF Focus (người gửi đối tượng, RoutedEventArss e) {TextBox tb = (TextBox) e.OrigenSource; đang chờ đợi Dispatcher.RunAsync (Windows.UI.Core.CoreDispatcherP Warriority.N normal, async () => {tb.Select ALL ();}); }
David Jones

1
#region TextBoxIDCard selection
private bool textBoxIDCardGotFocus = false;
private void TextBoxIDCard_GotFocus(object sender, RoutedEventArgs e)
{
    this.TextBoxIDCard.SelectAll();
}

private void TextBoxIDCard_LostFocus(object sender, RoutedEventArgs e)
{
    textBoxIDCardGotFocus = false;
}

private void TextBoxIDCard_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    if (textBoxIDCardGotFocus == false)
    {
        e.Handled = true;
        this.TextBoxIDCard.Focus();
        textBoxIDCardGotFocus = true;
    }
} 
#endregion

Nếu bạn có 20 hộp văn bản trên một cửa sổ, bạn sẽ tạo 3 phương thức cho mỗi hộp văn bản chứ? Cách tiếp cận này không tốt. Hãy xem tại đây: rachel53461.wordpress.com/2011/11/05/ từ
Alexandru Dicu

0

Điều này dường như làm việc tốt cho tôi. Về cơ bản nó là một bản tóm tắt của một số bài viết trước đó. Tôi chỉ cần đặt nó vào tệp MainWindow.xaml.cs của tôi trong hàm tạo. Tôi tạo hai trình xử lý, một cho bàn phím và một cho chuột và đưa cả hai sự kiện vào cùng một chức năng, HandleGotFocusEventđược xác định ngay sau hàm tạo trong cùng một tệp.

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

Đẹp và dễ dàng, nhưng dường như có một vấn đề về thời gian - mỗi lần thử khác (nhấp chuột), nó lại chọn lại ngay lập tức ...?
T4NK3R

0

Một cách dễ dàng để ghi đè mouseDown và chọn tất cả sau doubleclick là:

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

0

Hãy thử đặt cái này vào hàm tạo của bất kỳ điều khiển nào chứa trong hộp văn bản của bạn:

Loaded += (sender, e) =>
{
    MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
    myTextBox.SelectAll();
}

Cách tiếp cận này không hoạt động khi bạn đặt nó trong hàm tạo cửa sổ.
ViRuSTriNiTy

0

Nếu có một sự kiện bỏ chọn văn bản trong quá trình OnFocusdi chuột lên, tôi thường chỉ trì hoãn việc chọn tất cả.

private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
    if (TextBox.Text != null)
    {
        _ = Task.Run(() =>
        {
            Dispatcher.Invoke(
                async () => {
                    await Task.Delay(100);
                    TextBox.SelectAll();
                }
            );
        });
    }
}

-1

Tôi đã thử nghiệm tất cả trong số họ nhưng chỉ có các cách sau:

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

4
Đó cũng là một sự lạm dụng mã băm tục tĩu. Tôi đã đọc cái này, link
RichK

3
Và sử dụng GetType().Namethay vì ishoặc askhá hacky
RichK

-1

Tôi thấy rằng có rất nhiều câu trả lời, nhưng như đã được phê duyệt, các phương pháp nên được sử dụng là EditTextBoxGotCapture

với đoạn mã sau:

private void EditTextBoxGotCapture(object sender, MouseEventArgs e)
{
    if (sender is TextBox tb)
    {
        tb.Select(0, tb.Text.Length);
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.