Как автоматически выделить весь текст в фокусе в WPF TextBox? - PullRequest
204 голосов
/ 19 марта 2009

Если я вызываю SelectAll из обработчика событий GotFocus, он не работает с мышью - выбор исчезает, как только мышь отпускается.

РЕДАКТИРОВАТЬ: Людям нравится ответ Доннелле, я постараюсь объяснить, почему он мне не понравился так же, как принятый ответ.

  • Это более сложно, в то время как принятый ответ делает то же самое проще.
  • Юзабилити принятого ответа лучше. Когда вы щелкаете в середине текста, текст становится невыбранным, когда вы отпускаете мышь, позволяя мгновенно начать редактирование, и если вы все еще хотите выбрать все, просто нажмите кнопку еще раз, и на этот раз он не будет отменен при отпускании. Следуя рецепту Донеллы, если я нажму на середину текста, мне придется щелкнуть второй раз, чтобы иметь возможность редактировать. Если я щелкну где-нибудь внутри текста, а не за его пределами, это, скорее всего, означает, что я хочу начать редактирование, а не перезаписывать все.

Ответы [ 28 ]

4 голосов
/ 13 июля 2015

в файле 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();
    }

С этим кодом вы получаете доступ ко всем текстовым полям в вашем приложении.

3 голосов
/ 12 декабря 2014

Взято из здесь :

Зарегистрировать глобальный обработчик событий в файле 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();
}
2 голосов
/ 29 ноября 2011

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

В xaml у вас есть текстовое поле:

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

В коде позади:

private void SelectAll(object sender, MouseButtonEventArgs e)
{

    TextBox tb = (sender as TextBox);

    if (tb == null)
    {
        return;
    }

    if (!tb.IsKeyboardFocusWithin)
    {
        tb.SelectAll();
        e.Handled = true;
        tb.Focus();
    }
}
2 голосов
/ 27 марта 2018

Я понимаю, что это очень старо, но вот мое решение, которое основано на пространствах имен выражений / взаимодействия Microsoft и взаимодействий.

Сначала я следовал инструкциям по этой ссылке , чтобы поместить триггеры интерактивности в стиль.

Тогда все сводится к этому

        <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, и я использую это имя для элемента. Это прекрасно работает для меня. Просто примените стиль к любому текстовому полю, в котором вы хотите, чтобы весь текст выделялся при щелчке в текстовом поле.

Первый CallMethodAction вызывает функцию SelectAll текстового поля при возникновении события GotKeyboardFocus в текстовом поле.

Надеюсь, это поможет.

1 голос
/ 24 апреля 2013

У меня была такая же проблема. В VB.Net все так просто:

VB XAML:

<TextBox x:Name="txtFilterFrequency" />

Codehind:

Private Sub txtFilterText_GotFocus(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles txtFilterText.GotFocus
    Me.Dispatcher.BeginInvoke(Sub()
                                  txtFilterText.SelectAll()
                              End Sub, DispatcherPriority.ApplicationIdle, Nothing)
End Sub

C # (благодаря ViRuSTriNiTy)

private delegate void TextBoxSelectAllDelegate(object sender);

private void TextBoxSelectAll(object sender)
{
    (sender as System.Windows.Controls.TextBox).SelectAll();
}

private void MyTextBox_GotFocus(object sender, System.Windows.RoutedEventArgs e)
{
    TextBoxSelectAllDelegate d = TextBoxSelectAll;

    this.Dispatcher.BeginInvoke(d,
        System.Windows.Threading.DispatcherPriority.ApplicationIdle, sender);
}
1 голос
/ 12 сентября 2017

Это, безусловно, самое простое решение.

Добавить глобальный обработчик в приложение (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 SelectAll on Focus

Надеюсь, это поможет.

1 голос
/ 22 января 2018

Вот версия C # 1001 * ответа , отправленная @ 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.

1 голос
/ 17 февраля 2017

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

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 голос
/ 22 декабря 2011

Для тех, кто интересуется подходом Доннелле / Гроки, но хочет щелкнуть справа от последнего символа (но все еще внутри 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 голос
/ 23 января 2017

Я много искал решение, нашел несколько решений, чтобы выбрать все. Но проблема в том, что когда мы щелкаем правой кнопкой мыши и делаем вырез / копирование после выбора части текста из текстового поля, он выбирает все, даже если я выбрал часть текст. Чтобы это исправить, вот решение. Просто добавьте приведенный ниже код в событие выбора клавиатуры. Это сработало для меня.

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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...