Як автоматично вибрати весь текст на фокус у WPF TextBox?


232

Якщо я зателефонував SelectAllз GotFocusобробника подій, він не працює з мишею - виділення зникає, як тільки миша буде відпущена.

EDIT: Людям подобається відповідь Доннелл, я спробую пояснити, чому мені це не сподобалося так, як прийнята відповідь.

  • Він складніший, тоді як прийнята відповідь робить те саме, що простіше.
  • Корисність прийнятої відповіді краща. Коли ви клацаєте в середині тексту, текст відміняється, коли ви відпускаєте мишу, що дозволяє миттєво почати редагувати, і якщо ви все ще хочете вибрати все, просто натисніть кнопку ще раз, і на цей раз вона не скасує вибір при випуску. Слідуючи рецепту Донеллі, якщо я клацну посередині тексту, мені доведеться натиснути другий раз, щоб мати можливість редагувати. Якщо я натискаю десь усередині тексту, а не за межами тексту, це, швидше за все, означає, що я хочу почати редагування, а не перезаписувати все.

Якщо у вас буде більше однієї форми, її відповідь надалі стає менш складною, ніж перша. Використання обох варіантів є суперечливим, оскільки ви можете змінити спосіб роботи будь-якого з них.
thepaulpage

1
@Sergey: Можливо, ви захочете змінити прийняту відповідь на це питання, оскільки з тих пір були кращі відповіді. Я не збираюся пропонувати моє, але ви могли б;)
Грокис

Питання має тег Silverlight, але в Silverlight взагалі немає більшості подій / будь-яких подій попереднього перегляду. Який розчин слід використовувати для сріблястого світла?
Валентин Кузуб

Посилання "Чому фокус у WPF такий складний?" розбита
Максенція

1
як уже згадувалося в коментарі stackoverflow.com/a/2553297/492 нижче, madprops.org/blog/wpf-textbox-selectall-on-focus просте рішення і зберігає оригінальне поведінку носик. Я помістив реєстрацію події в конструкторі, тому що в додатку у мене є лише один елемент керування WPF.
CAD блокується

Відповіді:


75

Не знаю, чому він втрачає вибір у цьому GotFocusвипадку.

Але одне рішення - зробити вибір на події GotKeyboardFocusта GotMouseCaptureподії. Так завжди буде працювати.


10
Ні. Якщо натиснути мишкою в середині наявного тексту - виділення втрачається, як тільки відпускається кнопка миші.
Сергій Алдухов

3
Хоча - після другого клацання мишкою він знову вибирає весь текст ... Не впевнений, чи це призначена поведінка від дизайнерів WPF, але зручність використання не така вже й погана. Ще одна відмінність від одного обробника GotFocus полягає в тому, що натискання порожнього місця в TextBox вибирає все.
Сергій Алдухов

3
Це було і моє кулакове рішення. Але я виявив, що користувачі дуже роздратовані, коли вони не в змозі вибрати текст за допомогою миші, оскільки кожен раз, коли вони клацають весь текст, вибирається ...
Nils

1
Ще одним недоліком цього рішення є те, що при використанні меню "Вирізати / скопіювати / вставити" TextBox весь текст вибирається при виборі будь-якого пункту меню.

@gcores Я знаю, що це старе, але хтось знає, чому в події GotFocus вибраний текст втрачається? Ти маєш рацію про це, працюючи і в інших заходах, але це цілком прийнятне рішення в моїй книзі.
Feign

210

У нас це є, тому перший клік вибирає все, а інший клацання переходить до курсору (наша програма призначена для використання на планшетах із ручками).

Ви можете вважати його корисним.

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
Дуже дякую за це. Це чудово працює і має бути прийнятою відповіддю ІМХО. Вищевказаний код працює, коли TextBox отримує фокус за допомогою клавіатури або миші (і, мабуть, стилусом). +1
Дрю Ноакс

5
Тут я побачив майже однакову відповідь social.msdn.microsoft.com/Forums/en-US/wpf/thread/… , вона також працює, як ніколи не використовує e.OriginalSource, а також не проповзає через візуальне дерево. Чи є якась перевага робити все це?
Marco Luglio

1
Працює чудово, але було б ідеально, якби все-таки дозволяв перетягувати підбір тексту мишкою. Адресний рядок Google Chrome є прекрасним прикладом ідеальної системи: якщо користувач натискає та відпускає, не перетягуючи, весь текст виділяється. Однак якщо користувач натискає та перетягує, перетягування вибирає текст зазвичай, не вибираючи всіх. SelectAll відбувається лише при випуску миші . Я заграю і побачу, чи зможу я взагалі вдосконалити цей дизайн.
devios1

2
Ще одним недоліком цього рішення є те, що при використанні меню "Вирізати / скопіювати / вставити" TextBox весь текст вибирається при виборі будь-якого пункту меню.

1
Я виявив, що додатковий тест у SelectAllTextметоді textBox.IsFocusedпокращує його. Ви не хочете вибирати все, коли GetKeyboardFocusце пов’язано з вкладкою alt в програму.
Скотт Стаффорд

164

Відповідь Доннелл працює найкраще, але потребувати нового класу, щоб використовувати його, - це біль.

Замість цього я реєструю обробники обробників в App.xaml.cs для всіх TextBoxes у додатку. Це дозволяє мені використовувати відповідь Доннелл зі стандартним керуванням TextBox.

Додайте наступні методи до свого 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();
    }
}

4
Це досить круте рішення, його також описав Метт Гамільтон віків тому тут: madprops.org/blog/wpf-textbox-selectall-on-focus
Ешлі Девіс

Отримав помилки в написанні "отримує", "зосереджено"
Нейт Заугг,

2
Спасибі Нейт, виправлено, хоч у своєму захисті я хотів би зазначити, що орфографічні помилки були скопійовані дослівно з відповіді
Доннелле

Питання має тег Silverlight, але в Silverlight взагалі немає більшості подій / будь-яких подій попереднього перегляду. Який розчин слід використовувати для сріблястого світла? заздалегідь дякую
Валентин Кузуб

4
"Зосереджена орфографія набагато частіше зустрічається в США; однак сфокусований правопис іноді використовується у Великобританії та Канаді і особливо поширений в Австралії та Новій Зеландії". Так Nyah;)
Donnelle

85

Це досить старе, але я все одно покажу свою відповідь.

Я вибрав частину відповіді Доннелл (пропустив подвійний клацання), оскільки вважаю це більш природним. Однак, як і gcores, мені не подобається необхідність створення похідного класу. Але я також не люблю gcoresOnStartup метод . І це мені потрібно на принципі "загалом, але не завжди".

Я реалізував це як додане, DependencyPropertyщоб я міг встановити local:SelectTextOnFocus.Active = "True"в xaml. Я вважаю цей спосіб найбільш приємним.

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

Для моєї "загальної, але не завжди" функції я встановив цю властивість Attache Trueу (глобальній) TextBox Style. Таким чином, "Вибір тексту" завжди "увімкнено", але я можу відключити його на основі текстових скриньок.


8
+1 це набагато краще, ніж встановити його в усьому світі, і це більше "шлях WPF", ніж похідне від TextBox.
Стейн

3
+1 Згоден зі стиніном. "Сховати" код у app.cs не дуже добре для бідного розробника, який повинен з'ясувати, чому відбувається SelectAllOnFocus. :-) Я просто впустив це у свій клас для TextBoxBehaviors, а потім оновив базовий стиль TextBox. Працював частування. Ура
Лі Кемпбелл

2
@tronda: Просто додайте стиль до ресурсів за допомогою TargetType TextBox. Я пропоную вам подивитися на wpftutorial.net/Styles.html
Nils

2
Ще +1 за найкращу відповідь. Єдиною проблемою, яку я вважаю, є те, що текст вибирається завжди, навіть коли я використовую праву кнопку миші - що я часто роблю для редагування тексту через контекстне меню - рішення не працює в цьому випадку, оскільки він завжди вибирає весь текст, навіть якщо я просто хотів вирізати 1 слово через контекстне меню. Ви знаєте, як це виправити?
user3313608

2
Мені подобається ця відповідь, але навіщо вам розширювати DependencyObject? Я це видалив, і він все ще працює чудово.
Фред

47

Ось суміші поведінки, що реалізують рішення відповіді для вашої зручності:

Один для приєднання до одного TextBox:

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

І один для прикріплення до кореня контейнера, що містить кілька 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();
    }
}

Це, безумовно, найкраще і найчистіше рішення. Велике спасибі за те, що поділилися цим.
Голвелій

Це виглядає дійсно приємно, але чомусь він порушує управління вкладками ... Будь-яка ідея, чому?
Марк

Я хотів би скористатися вашим рішенням. Але справді загубився ... може, ти маєш зразок?
Хуан Пабло Гомес

Коли ви клацнете десь у текстовому полі, фокусуючись (уявіть, що хочете перенести карету в інше місце), він знову буде SelectAll замість переміщення каретки. Це несподівано. Виправлено це шляхом заміни GotMouseCapture на MouseDoubleClick, що є загальним явищем. Завдяки останнім рішенням від MSDN.
норехов

1
Схоже, це не працює, коли текстове поле отримує початковий фокус через FocusManager.FocusedElement. Будь-які ідеї чому?
szx

24

Хоча це давнє питання, у мене щойно була ця проблема, але я вирішив її за допомогою прикріпленої поведінки, а не висловлювальної поведінки, як у відповіді Сергія. Це означає, що мені не потрібна залежність від System.Windows.InteractivitySDK Blend:

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

Потім ви можете використовувати його у своєму XAML так:

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

Я тут про це блогував .


Мені подобається такий підхід, але методи Get / Set не повинні закінчуватися в "Властивості"; Мені довелося видалити це, щоб отримати код, після складання Xaml-частини.
Патрік Квірк

Дуже приємно, працювали так, як очікувалося. Мені це подобається, тому що це допомагає мені тримати проблеми, пов'язані з переглядом, при виконанні MVVM.
Killnine

16

Ось дуже хороше дуже просте рішення для MSDN :

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

Ось код позаду:

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
По суті, це те саме рішення, що і найбільш рейтингове в цій темі. Але оскільки це було на два роки раніше, тепер я знаю, де у @Donnelle позичив її;)
Сергій Алдухов,

Це рішення здавалося найлегшим і спрацювало для мене. Я хотів, щоб певний підмножина тексту, вибраного за замовчуванням, під час входу в текстове поле.
Джек Б Німбл

10

Я думаю, що це працює добре:

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. Я десь виявив код нижче (кредит надається), і він працює добре. Я розміщую його, навіть якщо це не пов'язане безпосередньо з питанням ОП, оскільки воно демонструє ту саму схему використання Dispatcherдля роботи з 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);
}

Я думаю, що це найпростіший спосіб реалізації. після створення методу розширення вам просто доведеться викликати myTextBox.SelectAllText (). Чому за цю відповідь не набрано більше балів? чому інші рішення настільки кращі?
Тоно Нам

2
Я б уникав цього методу, оскільки він покладається на виклик асинхронізації, який запускається після обробника MouseUp текстового поля. Я б не вважав, що це на 100% детерміновано, і це може призвести до непослідовної поведінки. Незважаючи на те, що це може бути малоймовірним, я б скоріше пішов із надійними методами, описаними вище.
Роб H

6

Ось спроба вирішити деякі проблеми з іншими рішеннями:

  1. Використовуючи контекстне меню правою кнопкою миші для вирізання / копіювання / минулого, вибирає весь текст, навіть якщо ви не вибрали його весь.
  2. При поверненні з контекстного меню правою кнопкою миші завжди вибирається весь текст.
  3. При поверненні до програми з Alt+Tab , весь текст вибирається завжди.
  4. Під час спроби виділити лише частину тексту під час першого клацання, все завжди вибирається (наприклад, на відміну від адресного рядка хромів Google).

Я написав код можна налаштувати. Ви можете вибрати на які дії вибрати все поведінка повинна відбуватися шляхом установки трьох полів тільки для читання: SelectOnKeybourdFocus, SelectOnMouseLeftClick,SelectOnMouseRightClick .

Мінус цього рішення полягає в тому, що він складніший і статичний стан зберігається. Це здається некрасивою боротьбою з поведінкою TextBoxконтролю за замовчуванням . Проте він працює, і весь код прихований у класі контейнера Attached Properties.

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

Щоб приєднати вкладений ресурс до а TextBox, все, що вам потрібно зробити, - це додати простір імен xml ( xmlns) вкладеного ресурсу та використовувати його так:

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

Деякі зауваження щодо цього рішення:

  1. Щоб змінити поведінку за замовчуванням події вниз миші та включити вибір лише частини тексту під час першого клацання, у події миші вибирається весь текст.
  2. Мені довелося мати справу з тим, що TextBoxпам'ятає його вибір після того, як він втрачає увагу. Я насправді відмінив таку поведінку.
  3. Мені довелося пам'ятати, чи перша кнопка миші вниз - це перша дія на TextBox(FirstActionIsMouseDown статичне поле).
  4. Мені довелося запам’ятати контекстне меню, відкрите правою кнопкою миші ( ContextMenuстатичне поле).

Єдиний побічний ефект, який я виявив, коли SelectOnMouseRightClickце правда. Іноді контекстне меню правою кнопкою миші мерехтить, коли його відкрите та клацання правою кнопкою миші на порожньому TextBoxзначенні не робить "вибору всіх".


5

Я не знайшов жодної з представлених тут відповідей, що не імітують стандартне текстове поле Windows. Наприклад, спробуйте клацнути в пробілі між останнім символом текстового поля та правою частиною текстового поля. Більшість рішень тут завжди вибиратиме весь вміст, що ускладнює додавання тексту до текстового поля.

Відповідь, яку я тут представляю, поводиться краще в цьому відношенні. Це поведінка (для цього потрібна збірка System.Windows.Interactivity від SDK Blend ). Він може бути переписаний, використовуючи також додані властивості.

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

Це засновано на коді, який я знайшов тут .


1
Хоча це хороша відповідь, я думаю, що коли користувач натискає на пробіл, його намір (у бізнес-додатку), швидше за все, перекриє все значення, тому вибір усіх - це правильний підхід.
Сергій Алдухов

1
Сергій: перший клацання вибере все значення, другий клацання поставить курсор праворуч від значення. В інших представлених рішеннях другий клацання дозволить зберегти вибране ціле значення, що ускладнить додавання значення.
Крістоф Верб'єст

Як це використовується? Я додав цей код до App.xaml.cs, але, схоже, це не вплинуло на TextBoxes у моєму додатку.
PIntag

5

Ця проста реалізація прекрасно працює для мене:

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

Щоб застосувати його до всіх TextBox, поставте наступний код післяInitializeComponent();

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

4

У файлі App.xaml:

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

У файлі App.xaml.cs:

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

За допомогою цього коду ви досягаєте всіх TextBoxу своїй заявці.


3

Взято звідси :

Зареєструйте обробник глобальних подій у файлі App.xaml.cs:

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

3

Я розумію, що це дуже старе, але ось моє рішення, яке базується на просторах імен виразів / мікрософт та взаємодій.

По-перше, я дотримувався вказівок за цим посиланням, щоб розмістити тригери інтерактивності у стилі.

Тоді зводиться до цього

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

і це

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

У моєму випадку у мене є керування користувачем, де знаходяться текстові поля, які мають позаду коду. Код позаду має функцію обробника. Я дав моєму користувачеві керувати ім'ям у XAML, і я використовую це ім'я для елемента. Це прекрасно працює для мене. Просто застосуйте стиль до будь-якого місця, TextBoxде ви хочете, щоб весь текст був вибраний при натисканні кнопки TextBox.

Перший CallMethodActionвикликає SelectAllметод текстового поля, коли GotKeyboardFocusподія на TextBoxпожежах.

Я сподіваюся, що це допомагає.


Оскільки це такі старі запитання, це може допомогти вашій відповіді привернути увагу, якщо ви згадаєте, чому хтось може обрати такий підхід.
дівібісан

По-перше, це не потрібно вкладати у стиль, але я вважаю очевидним, що існує багато елементів управління текстовим полем, які потребують цього, стиль - це шлях.
wiyosaya

1
Можливо, деякі не погоджуються з таким підходом, однак, для того, чому ви можете використовувати цей підхід, він не потребує підкласифікації TextBox, реєстрації подій обробника класів, методів розширення, створення доданих властивостей і т. Д. Як стиль, він також може бути доданий до словника ресурсів будь-якого xaml проекту. Без ключа x: він застосовуватиметься до будь-якого екземпляра TextBox у межах словника ресурсів, не змінюючи xaml кожного окремого текстового поля. У деяких випадках це може бути більш чистий підхід.
wiyosaya

2

Я використав відповідь Нілса, але перейшов на більш гнучку.

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

1
Дійсно гарне рішення для використання в шаблонах, оскільки ви можете прив’язати його до xaml без фактичного коду позаду, просто розширеної поведінки текстового поля.
Ерік Йоханссон

2

Ось версія C # відповіді, опублікована @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);
}

тоді MyTextBox_GotFocusяк обробник подій призначений для GotFocusподії MyTextBox.


2

У мене є дещо спрощена відповідь на це (тільки з PreviewMouseLeftButtonDownподією), який, здається, імітує звичайну функціональність браузера:

У XAML ви маєте TextBoxсказати:

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

1
Можливо, ви хочете додати подію GotKeyboardFocus з TextBox.SelectAll () всередину для людей, які переглядають вашу програму. Ваше рішення працює і для PasswordBoxes (оскільки паролі PasswordBoxes є герметичними, їх не можна продовжувати).
Девід Шеррет

1

Спробуйте цей метод розширення, щоб додати бажану поведінку до будь-якого елемента управління TextBox. Я його ще не перевіряв широко, але, здається, відповідає моїм потребам.

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

Я багато шукав рішення, знайшов пару рішень для selectall Але проблема полягає в тому, коли ми робимо клацання правою кнопкою миші і робимо вирізання / копіювання після вибору частини тексту з текстового поля, вона вибирає все, навіть я вибрав частину тексту. Виправити це тут - рішення. Просто додайте наведений нижче код у події вибору клавіатури. Це працювало для мене.

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

У мене була така ж проблема. У VB.Net це легко працює таким чином:

VB XAML:

<TextBox x:Name="txtFilterFrequency" />

За кодом:

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

Краще рішення для мене, я вже відправив C # переклад тут: stackoverflow.com/a/48385409/3936440
ViRuSTriNiTy

Для мене такий підхід час від часу не вдається вибрати текст. Я думаю, що це стан гонки завдяки BeginInvoke.
Ваймс

Будь ласка уточніть. Пріоритет диспетчера працює над типовими програмами, як очікувалося. Яка у вас ситуація? Ви спробували точно, як описано? Щось особливе у вашому рішенні?
Nasenbaer

1

Це, безумовно, найпростіше рішення.

Додайте глобальний обробник до програми (App.xaml.cs) і готово. Вам знадобиться лише кілька рядків коду.

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

    base.OnStartup(e);
}

Тому використовуйте клас EventManager, щоб зареєструвати обробник глобальних подій щодо типу (TextBox). Фактичний обробник мертвий простий:

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

Перевірте тут: WPF TextBox SelectAll on Focus

Сподіваюся, це допомагає.


1

Для тих, хто зацікавлений у підході Доннелл / Грокі, але хочу натиснути праворуч останнього персонажа (але все ще в межах 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Метод був узятий з цього поста.


1
Добре працює, але подія подвійного клацання не спрацьовує
Родріго Кабалеро

Насправді він входить до події подвійного клацання, але властивість OriginalSource має тип TextBoxView. Отже, метод SelectAllText повинен бути таким: приватна статична недійсна SelectAllText (відправник об'єкта, RoutedEventArgs e) {var textBox = e.OriginalSource як TextBox; if (textBox! = null) {textBox.SelectAll (); System.Diagnostics.Debug.WriteLine ("Вибране ВСЕ"); } else if (відправник TextBox) {(відправник як TextBox) .SelectAll (); }
Родріго Кабалеро

1

Після гуглінгу та тестування я знайшов просте рішення, яке працювало на мене.

Вам потрібно додати обробник подій до 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();
        }
    }
}

Тепер ви можете додати SelectAll()команду для GotFocusобробників подій до будь-яких TextBoxелементів управління окремо:

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

Ваш текст зараз обраний на фокус!

Адаптовано з рішення доктора WPF, форумів MSDN


Я щойно використав: приватний асинхронічний недійсний TBTime_GotFocus (відправник об'єкта, RoutedEventArgs e) {TextBox tb = (TextBox) e.OriginalSource; чекайте Dispatcher.RunAsync (Windows.UI.Core.CoreDispatcherPriority.Normal, async () => {tb.SelectAll ();}); }
Девід Джонс

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

Якщо у вас на вікні 20 текстових полів, ви створите 3 методи для кожного текстового поля? Такий підхід не є хорошим. Подивіться тут: rachel53461.wordpress.com/2011/11/05/…
Олександру

0

Це, здається, добре працює для мене. Це в основному резюме деяких попередніх постів. Я просто помістив це у свій файл 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();
}

Приємно та легко, але, схоже, є проблеми із тимчасовим терміном - кожен другий спробу (клацання миші) він знову відбирає негайно ...?
T4NK3R

0

Найпростіший спосіб перемогти мишуDown та вибрати все після подвійного клацання:

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

Спробуйте помістити це в конструктор будь-якого контролю, який містить ваш текстовий ящик:

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

Цей підхід не працює, коли ви помістите це в конструктор вікон.
VIRuSTriNiTy

0

Якщо є подія, яка скасовує вибір тексту під час OnFocusмиші вгору, я зазвичай просто затримую виділити все.

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

-1

Я протестував їх усіх, але розробив лише наступне:

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
Це також непристойне зловживання хеш-кодами. Я прочитав це посилання
RichK

3
І використовувати GetType().Nameзамість цього isабо asдосить
гакітно

-1

Я бачу, що відповідей дуже багато, але як схвалена, методи, які слід використовувати EditTextBoxGotCapture

із наступним кодом:

private void EditTextBoxGotCapture(object sender, MouseEventArgs e)
{
    if (sender is TextBox tb)
    {
        tb.Select(0, tb.Text.Length);
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.