¿Cómo seleccionar automáticamente todo el texto en foco en WPF TextBox?

232

Si llamo SelectAlldesde unGotFocus controlador de eventos, no funciona con el mouse; la selección desaparece tan pronto como se suelta el mouse.

EDITAR: A la gente le gusta la respuesta de Donnelle, intentaré explicar por qué no me gustó tanto como la respuesta aceptada.

  • Es más complejo, mientras que la respuesta aceptada hace lo mismo de una manera más simple.
  • La usabilidad de la respuesta aceptada es mejor. Cuando hace clic en el medio del texto, el texto no se selecciona cuando suelta el mouse, lo que le permite comenzar a editar instantáneamente, y si aún desea seleccionar todo, simplemente presione el botón nuevamente y esta vez no se anulará la selección. Siguiendo la receta de Donelle, si hago clic en el medio del texto, tengo que hacer clic por segunda vez para poder editar. Si hago clic en algún lugar dentro del texto en lugar de fuera del texto, lo más probable es que quiera comenzar a editar en lugar de sobrescribir todo.
Sergey Aldoukhov
fuente
Si va a tener más de una forma, su respuesta sigue siendo menos compleja que la primera. La usabilidad de ambas opciones es discutible, ya que puede cambiar el funcionamiento de cualquiera de ellas.
thepaulpage
1
@Sergey: es posible que desee cambiar la respuesta aceptada para esta pregunta, ya que ha habido mejores respuestas desde entonces. No voy a sugerir el mío, pero podrías;)
Grokys
La pregunta tiene la etiqueta Silverlight, pero Silverlight no tiene la mayoría de los eventos / ningún tipo de eventos de vista previa. ¿Qué solución debería usarse para Silverlight entonces?
Valentin Kuzub
Enlace "¿Por qué el enfoque en WPF es tan complicado?" está roto
Maxence
1
Como se menciona en un comentario en stackoverflow.com/a/2553297/492 a continuación, madprops.org/blog/wpf-textbox-selectall-on-focus es una solución fácil y preserva el comportamiento original del ruido. Puse el registro de eventos en el constructor porque solo tengo un control WPF en la aplicación.
CAD bloke

Respuestas:

75

No sé por qué pierde la selección en el GotFocusevento.

Pero una solución es hacer la selección en GotKeyboardFocusy los GotMouseCaptureeventos. De esa manera siempre funcionará.

gcores
fuente
10
No Al hacer clic con el mouse en el medio del texto existente, la selección se pierde tan pronto como se suelta el botón del mouse.
Sergey Aldoukhov
3
Sin embargo, después de un segundo solo clic, selecciona todo el texto nuevamente ... No estoy seguro si es un comportamiento previsto de los diseñadores de WPF, pero la usabilidad no es tan mala. Otra diferencia de un solo controlador GotFocus es que al hacer clic en un espacio vacío en el cuadro de texto se selecciona todo.
Sergey Aldoukhov
3
Esta fue mi primera solución, también. Pero descubrí que los usuarios están realmente molestos cuando no pueden seleccionar Texto con el mouse, porque cada vez que hacen clic se selecciona todo el texto ...
Nils
1
Otro inconveniente de esta solución es que cuando utiliza el menú "Cortar / Copiar / Pegar" de TextBox, se selecciona todo el texto cuando selecciona cualquier elemento del menú.
@ gcores Sé que esto es viejo, pero ¿alguien sabe por qué en el evento GotFocus se pierde el texto seleccionado? Sin embargo, tienes razón al trabajar en otros eventos y esa es una solución perfectamente aceptable en mi libro.
Fingir el
210

Lo tenemos para que el primer clic seleccione todo, y otro clic va al cursor (nuestra aplicación está diseñada para usar en tabletas con bolígrafos).

Tu podrias encontrar esto útil.

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();
    }
}
Donnelle
fuente
99
Muchas gracias por esto. Esto funciona de maravilla y debería ser la respuesta aceptada en mi humilde opinión. El código anterior funciona cuando TextBox recibe el foco a través del teclado o el mouse (y aparentemente el lápiz). +1
Drew Noakes
55
Vi una respuesta casi idéntica aquí social.msdn.microsoft.com/Forums/en-US/wpf/thread/… , también funciona, siempre que no usa e.OriginalSource, ni se arrastra por el árbol visual. ¿Hay alguna ventaja en hacer todo esto?
Marco Luglio
1
Funciona muy bien, pero sería perfecto si todavía permitiera arrastrar la selección de texto con el mouse. La barra de direcciones de Google Chrome es un ejemplo perfecto del sistema ideal: si el usuario hace clic y suelta sin arrastrar, se resalta todo el texto. Sin embargo, si el usuario hace clic y arrastra, el arrastre selecciona el texto normalmente sin seleccionar todo. SelectAll solo ocurre al soltar el mouse . Voy a tocar el violín y ver si puedo mejorar este diseño.
devios1
2
Otro inconveniente de esta solución es que cuando utiliza el menú "Cortar / Copiar / Pegar" de TextBox, se selecciona todo el texto cuando selecciona cualquier elemento del menú.
1
Descubrí que una prueba adicional en el SelectAllTextmétodo de textBox.IsFocusedmejora. No querrás seleccionar todo cuando GetKeyboardFocusse deba al uso alternativo del programa.
Scott Stafford
164

La respuesta de Donnelle funciona mejor, pero tener que derivar una nueva clase para usarla es una molestia.

En lugar de hacerlo, registro los controladores en App.xaml.cs para todos los cuadros de texto de la aplicación. Esto me permite usar la respuesta de Donnelle con el control TextBox estándar.

Agregue los siguientes métodos a su 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();
    }
}
Grokys
fuente
44
Esta es una solución genial, también fue descrita por Matt Hamilton hace años aquí: madprops.org/blog/wpf-textbox-selectall-on-focus
Ashley Davis
Tengo algunos errores ortográficos en 'recibe', 'enfocado'
Nate Zaugg
2
Gracias, Nate, corregido, aunque en mi defensa me gustaría señalar que los errores ortográficos se copiaron textualmente de la respuesta de Donnelle;)
Grokys
La pregunta tiene la etiqueta Silverlight, pero Silverlight no tiene la mayoría de los eventos / ningún tipo de eventos de vista previa. ¿Qué solución debería usarse para Silverlight entonces? gracias de antemano
Valentin Kuzub
44
"La ortografía enfocada es mucho más común en los Estados Unidos; sin embargo, la ortografía enfocada a veces se usa en el Reino Unido y Canadá, y es especialmente común en Australia y Nueva Zelanda". So nyah;)
Donnelle
85

Esto es bastante antiguo, pero mostraré mi respuesta de todos modos.

Elegí parte de la respuesta de Donnelle (omití el doble clic) porque creo que es más natural. Sin embargo, al igual que gcores, no me gusta la necesidad de crear una clase derivada. Pero tampoco me gusta el OnStartupmétodo gcores . Y necesito esto sobre una base "generalmente pero no siempre".

He implementado esto como adjunto DependencyPropertypara poder configurarlo local:SelectTextOnFocus.Active = "True"en xaml. De esta manera me parece lo más agradable.

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

Para mi característica "general pero no siempre" configuré esta propiedad Attache Trueen a (global) TextBox Style. De esta forma, "seleccionar el texto" siempre está "activado", pero puedo deshabilitarlo por cuadro de texto.

Nils
fuente
8
+1 es mucho mejor que configurarlo globalmente, y es más 'la forma WPF' que derivar de TextBox.
stijn
3
+1 De acuerdo con stijn. "Ocultar" su código en la app.cs no es bueno para el pobre desarrollador que tiene que descubrir por qué está sucediendo SelectAllOnFocus. :-) Acabo de dejar esto en mi clase para TextBoxBehaviors y luego actualicé mi estilo base de TextBox. Trabajó un placer. Saludos
Lee Campbell
2
@tronda: simplemente agregue un estilo a los recursos utilizando un TargetType de TextBox. Le sugiero que eche un vistazo a wpftutorial.net/Styles.html
Nils
2
Otro +1 para la mejor respuesta. El único problema que encuentro es que el texto siempre se selecciona incluso cuando uso el botón derecho del mouse, lo que hago con frecuencia para editar el texto a través del menú contextual, la solución no funciona para este caso porque siempre selecciona todo el texto incluso si yo solo quería cortar 1 palabra a través del menú contextual. ¿Saben cómo arreglar esto?
user3313608
2
Me gusta esta respuesta, pero ¿por qué tienes que extender DependencyObject? Quité eso y todavía funciona bien.
Fred
47

Estos son los comportamientos de Blend que implementan la solución de respuesta para su conveniencia:

Uno para adjuntar a un solo cuadro de texto:

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

Y uno para adjuntar a la raíz de un contenedor que contiene múltiples 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();
    }
}
Sergey Aldoukhov
fuente
Esta es, con mucho, la mejor y más limpia solución. Muchas gracias por compartirlo.
Golvellius
Se ve muy bien, pero por alguna razón rompe el control de pestañas ... ¿Alguna idea de por qué?
Marc
Me gustaría usar su solución. Pero realmente perdido ... tal vez tienes una muestra?
Juan Pablo Gomez
Cuando hace clic en algún lugar del cuadro de texto mientras tiene el foco (imagine que desea mover el cursor a otro lugar), seleccionará Todo nuevamente en lugar de mover el cursor. Es inesperado Se solucionó reemplazando GotMouseCapture con MouseDoubleClick, que es común. Gracias a las últimas soluciones de MSDN.
norekhov
1
Parece que no funciona cuando el cuadro de texto recibe el foco inicial a través de FocusManager.FocusedElement. Alguna idea de por qué?
szx
24

Aunque esta es una vieja pregunta, acabo de tener este problema, pero lo resolví usando un Comportamiento Adjunto, en lugar de un Comportamiento de Expresión como en la respuesta de Sergey. Esto significa que no necesito una dependencia System.Windows.Interactivityen el SDK de 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();
    }
}

Luego puede usarlo en su XAML de esta manera:

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

Blogueé sobre esto aquí .

Deberes
fuente
Me gusta este enfoque, pero los métodos Get / Set no deberían terminar en "Propiedad"; Tuve que eliminar eso para obtener el código compilado después de agregar la porción Xaml.
Patrick Quirk
Muy agradable, funcionó exactamente como se esperaba. Me gusta esto porque me ayuda a mantener las preocupaciones de Vista separadas cuando hago MVVM.
Killnine
16

Aquí hay una muy buena solución muy simple en MSDN :

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

Aquí está el código detrás:

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();
        }
    }
}
BillBR
fuente
1
Esencialmente, esta es la misma solución que la más calificada en este hilo. Pero ya que dos años antes, ahora sé de dónde lo tomó prestado @Donnelle;)
Sergey Aldoukhov
Esta solución me pareció la más fácil y funcionó para mí. Quería un subconjunto específico de texto seleccionado por defecto al ingresar al cuadro de texto.
Jack B Nimble
10

Creo que esto funciona bien:

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

Si desea implementarlo como un método de extensión:

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

Y en tu GotFocuscaso:

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

Descubrí la solución anterior porque hace varios meses estaba buscando una manera de enfocarme en un determinado UIElement. Descubrí el código a continuación en alguna parte (se otorga crédito) y funciona bien. Lo publico a pesar de que no está directamente relacionado con la pregunta del OP porque demuestra el mismo patrón de uso Dispatcherpara trabajar con 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);
}
Sam
fuente
Supongo que este es el método más simple de implementar. después de crear el método de extensión, solo tendrá que llamar a myTextBox.SelectAllText (). ¿Por qué esta respuesta no recibió más puntos? ¿Por qué las otras soluciones son mucho mejores?
Tono Nam
2
Evitaría este método porque depende de una llamada asíncrona para ejecutarse después del controlador MouseUp del cuadro de texto. No confiaría en que esto sea 100% determinista y que pueda conducir a un comportamiento inconsistente. Aunque es poco probable que ocurra, prefiero seguir los métodos infalibles anteriores.
Rob H
6

Aquí hay un intento de resolver algunos de los problemas con otras soluciones:

  1. El uso del menú contextual del botón derecho para cortar / copiar / pegar selecciona todo el texto, incluso si no lo seleccionó todo.
  2. Al regresar del menú contextual del botón derecho, todo el texto siempre está seleccionado.
  3. Al volver a la aplicación con Alt+Tab , todo el texto siempre está seleccionado.
  4. Al intentar seleccionar solo una parte del texto en el primer clic, todo está siempre seleccionado (a diferencia de la barra de direcciones de cromos de Google, por ejemplo).

El código que escribí es configurable. Se puede elegir en las acciones que el seleccionar todo comportamiento debe ocurrir mediante el establecimiento de tres campos de sólo lectura: SelectOnKeybourdFocus, SelectOnMouseLeftClick,SelectOnMouseRightClick .

La desventaja de esta solución es que es más compleja y se almacena el estado estático. Parece una lucha fea con el comportamiento predeterminado del TextBoxcontrol. Aún así, funciona y todo el código está oculto en la clase de contenedor Propiedad adjunta.

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

Para adjuntar la propiedad adjunta a un TextBox, todo lo que necesita hacer es agregar el espacio de nombres xml ( xmlns) de la propiedad adjunta y luego usarlo así:

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

Algunas notas sobre esta solución:

  1. Para anular el comportamiento predeterminado de un evento de mouse down y permitir seleccionar solo una parte del texto con el primer clic, todo el texto se selecciona en el evento de mouse up.
  2. Tuve que lidiar con el hecho de que el TextBoxrecuerda su selección después de que pierde el foco. De hecho, he anulado este comportamiento.
  3. Tenía que recordar si un botón del mouse hacia abajo es la primera acción en el TextBox(FirstActionIsMouseDown campo estático).
  4. Tenía que recordar el menú contextual abierto con un clic derecho ( ContextMenucampo estático).

El único efecto secundario que encontré es cuando SelectOnMouseRightClickes cierto. A veces, el menú contextual del botón derecho parpadea cuando se abre y al hacer clic derecho en un espacio en blanco TextBoxno se selecciona "seleccionar todo".

Eliahu Aaron
fuente
5

No he encontrado que ninguna de las respuestas presentadas aquí imite un cuadro de texto estándar de Windows. Por ejemplo, intente hacer clic en el espacio en blanco entre el último carácter del cuadro de texto y el lado derecho del cuadro de texto. La mayoría de las soluciones aquí siempre seleccionarán todo el contenido, lo que hace que sea muy difícil agregar texto a un cuadro de texto.

La respuesta que presento aquí se comporta mejor a este respecto. Es un comportamiento (por lo que requiere el ensamblaje System.Windows.Interactivity del Blend SDK ). También podría reescribirse usando las propiedades adjuntas.

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

Esto se basa en el código que encontré aquí .

Kristof Verbiest
fuente
1
Si bien esta es una buena respuesta, creo que cuando el usuario hace clic en el espacio en blanco, lo más probable es que su intención (en una aplicación comercial) anule todo el valor, por lo que seleccionar todo es el enfoque correcto.
Sergey Aldoukhov
1
Sergey: el primer clic seleccionará el valor completo, el segundo clic colocará el cursor a la derecha del valor. En las otras soluciones presentadas, el segundo clic mantendrá todo el valor seleccionado, lo que hace que sea muy difícil agregarlo.
Kristof Verbiest
¿Cómo se usa esto? Agregué este código a App.xaml.cs pero no pareció tener efecto en los TextBoxes en mi aplicación.
PIntag
5

Esta implementación simple funciona perfectamente para mí:

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

Para aplicarlo a todos TextBox, coloque el siguiente código despuésInitializeComponent();

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

En el archivo App.xaml:

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

En el archivo App.xaml.cs:

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

Con este código llega a todos TextBoxen su aplicación.

Darshan Faldu
fuente
3

Tomado de aquí :

Registre el controlador de eventos global en el archivo App.xaml.cs:

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

    base.OnStartup(e);
}

Entonces el controlador es tan simple como:

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

Me doy cuenta de que esto es muy antiguo, pero aquí está mi solución que se basa en las expresiones / interactividad de Microsoft y los espacios de nombres de interacciones.

Primero, seguí las instrucciones en este enlace para colocar los disparadores de interactividad en un estilo.

Entonces todo se reduce a esto

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

y esto

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

En mi caso, tengo un control de usuario donde están los cuadros de texto que tienen un código subyacente. El código subyacente tiene la función de controlador. Le di a mi usuario un nombre de control en XAML y estoy usando ese nombre para el elemento. Esto está funcionando perfectamente para mí. Simplemente aplique el estilo a cualquier lugar TextBoxdonde le gustaría tener todo el texto seleccionado al hacer clic en elTextBox .

El primero CallMethodActionllama al SelectAllmétodo del cuadro de texto cuando se dispara el GotKeyboardFocusevento TextBox.

Espero que esto ayude.

wiyosaya
fuente
Dado que esta es una pregunta tan antigua, podría ayudar a que su respuesta reciba cierta atención si menciona por qué alguien podría elegir este enfoque.
divibisan
En primer lugar, esto no necesita ponerse en un estilo, pero creo que es obvio que hay muchos controles de cuadros de texto que lo necesitan, un estilo es el camino a seguir.
wiyosaya
1
Tal vez algunos no estén de acuerdo con este enfoque, sin embargo, en cuanto a por qué podría usar este enfoque, no requiere subclasificar TextBox, registrar eventos de controlador de clase, métodos de extensión, crear propiedades adjuntas, etc. Como estilo, también podría agregarse al diccionario de recursos de cualquier proyecto xaml. Sin la clave x:, se aplicaría a cualquier instancia de TextBox dentro del alcance del diccionario de recursos sin tener que modificar el xaml de cada cuadro de texto individual. En algunos casos, puede ser un enfoque más limpio.
wiyosaya
2

He usado la respuesta de Nils pero la he convertido a una más flexible.

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

En XAML, puede usar uno de estos:

<!-- 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" />
bafsar
fuente
1
Muy buena solución para usar en plantillas, ya que puede vincularlo a xaml sin ningún código real detrás, solo un comportamiento extendido del cuadro de texto.
Eric Johansson
2

Aquí está la versión C # de la respuesta publicada por @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);
}

mientras MyTextBox_GotFocusque el controlador de eventos está asignado al GotFocusevento de MyTextBox.

ViRuSTriNiTy
fuente
2

Tengo una respuesta ligeramente simplificada para esto (con solo el PreviewMouseLeftButtonDownevento) que parece imitar la funcionalidad habitual de un navegador:

En XAML tienes algo que TextBoxdecir:

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

En código detrás:

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();
    }
}
Danield
fuente
1
Es posible que desee agregar un evento GotKeyboardFocus con TextBox.SelectAll () dentro para las personas que se abren paso en su aplicación. Su solución también funciona para PasswordBoxes (dado que PasswordBoxes son tipos sellados, no se pueden extender).
David Sherret
1

Pruebe este método de extensión para agregar el comportamiento deseado a cualquier control TextBox. Todavía no lo he probado exhaustivamente, pero parece satisfacer mis necesidades.

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();
            }
        }
    }
}
David Kirkland
fuente
1

Busqué mucho la solución, encontré un par de soluciones para seleccionar, pero el problema es que cuando hacemos clic derecho y cortamos / copiamos después de seleccionar parte del texto del cuadro de texto, selecciona todo incluso seleccioné parte del texto. Para solucionar esto aquí está la solución. Simplemente agregue el siguiente código en el evento de selección de teclado. Esto funcionó para mí.

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();
}
Sambu Praveen
fuente
1

Tuve el mismo problema En VB.Net funciona fácil de esa manera:

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 # (gracias a 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);
}
Nasenbaer
fuente
La mejor solución para mí, he publicado una traducción de C # aquí: stackoverflow.com/a/48385409/3936440
ViRuSTriNiTy
Para mí, este enfoque ocasionalmente no puede seleccionar texto. Creo que es condición de carrera debido a BeginInvoke.
Vimes
Por favor especifica. La prioridad del despachador está funcionando en las aplicaciones predeterminadas como se esperaba. Cual es tu situacion ¿Intentaste exactamente como se describe? ¿Algo especial en tu solución?
Nasenbaer
1

Esta es, con mucho, la solución más simple.

Agregue un controlador global a la aplicación (App.xaml.cs) y listo. Necesitará solo unas pocas líneas de código.

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

    base.OnStartup(e);
}

Por lo tanto, use la clase EventManager para registrar un controlador de eventos global en un tipo (TextBox). El controlador real es muy simple:

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

Marque aquí: WPF TextBox SelectAll en foco

Espero eso ayude.

Marlon Assef
fuente
1

Para aquellos interesados ​​en el enfoque de Donnelle / Groky, pero quieren un clic a la derecha del último carácter (pero aún dentro del TextBox) para colocar el cursor al final del texto ingresado, se me ocurrió esta solución:

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

El GetRoundedCharacterIndexFromPointmétodo fue tomado de esta publicación.

Pentag
fuente
1
Funciona bien, pero el evento de doble clic no se activa
Rodrigo Caballero
En realidad, ingresa al evento de doble clic, pero la propiedad OriginalSource es del tipo TextBoxView. Entonces, el método SelectAllText debería ser así: vacío estático privado SelectAllText (remitente de objeto, RoutedEventArgs e) {var textBox = e.OriginalSource como TextBox; if (textBox! = null) {textBox.SelectAll (); System.Diagnostics.Debug.WriteLine ("Selected ALL"); } else if (el remitente es TextBox) {(remitente como TextBox) .SelectAll (); }
Rodrigo Caballero
1

Después de buscar en Google y probar, encontré una solución simple que funcionó para mí.

Debe agregar un controlador de Loadedeventos al evento de su ventana de contenedor:

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

A continuación, debe crear el controlador para el referenciado RoutedEventHandleren el código anterior:

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

Ahora, puede agregar el SelectAll()comando en los GotFocuscontroladores de eventos a cualquier TextBoxcontrol por separado:

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

Su texto ahora está seleccionado en foco!

Adaptado de la solución Dr. WPF, foros de MSDN

DonBeto97
fuente
Acabo de usar: privado async void TBTime_GotFocus (remitente de objeto, RoutedEventArgs e) {TextBox tb = (TextBox) e.OriginalSource; aguarde Dispatcher.RunAsync (Windows.UI.Core.CoreDispatcherPriority.Normal, async () => {tb.SelectAll ();}); }
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
Brian
fuente
Si tiene 20 cuadros de texto en una ventana, ¿creará 3 métodos para cada cuadro de texto? Este enfoque no es bueno. Eche un vistazo aquí: rachel53461.wordpress.com/2011/11/05/…
Alexandru Dicu
0

Esto parece funcionar bien para mí. Básicamente es un resumen de algunas publicaciones anteriores. Acabo de poner esto en mi archivo MainWindow.xaml.cs en el constructor. Creo dos controladores, uno para el teclado y otro para el mouse, y canalizo ambos eventos en la misma función HandleGotFocusEvent, que se define justo después del constructor en el mismo archivo.

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();
}
Ted
fuente
Agradable y fácil, pero parece tener un problema de tiempo: cada dos intentos (clic del mouse), se vuelve a seleccionar de inmediato ...?
T4NK3R
0

Una manera fácil de anular el mouseDown y seleccionar todo después de hacer doble clic es:

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

Intente poner esto en el constructor de cualquier control que contenga su cuadro de texto:

Loaded += (sender, e) =>
{
    MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
    myTextBox.SelectAll();
}
CodeOtaku
fuente
Este enfoque no funciona cuando coloca esto en un constructor de ventanas.
ViRuSTriNiTy
0

Si hay un evento que deselecciona el texto durante el OnFocusmouse, usualmente solo retraso la selección de todo.

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

Los he probado todos, pero solo funcionó lo siguiente:

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();
}
Ehsan Zargar Ershadi
fuente
44
Eso también es un mal uso obsceno de los códigos hash. Leí esto, enlace
RichK
3
Y usar en GetType().Namelugar de iso ases bastante hacky
RichK
-1

Veo que hay muchas respuestas, pero como la aprobada, los métodos que deben usarse son EditTextBoxGotCapture

con el siguiente código detrás:

private void EditTextBoxGotCapture(object sender, MouseEventArgs e)
{
    if (sender is TextBox tb)
    {
        tb.Select(0, tb.Text.Length);
    }
}
Liviu Sosu
fuente