Come selezionare automaticamente tutto il testo attivo in WPF TextBox?


232

Se chiamo SelectAllda un GotFocusgestore di eventi, non funziona con il mouse: la selezione scompare non appena viene rilasciato il mouse.

EDIT: Alla gente piace la risposta di Donnelle, cercherò di spiegare perché non mi è piaciuta tanto quanto la risposta accettata.

  • È più complesso, mentre la risposta accettata fa la stessa cosa in modo più semplice.
  • L'usabilità della risposta accettata è migliore. Quando si fa clic nel mezzo del testo, il testo viene deselezionato quando si rilascia il mouse per consentire di iniziare immediatamente la modifica e, se si desidera ancora selezionare tutto, premere nuovamente il pulsante e questa volta non verrà deselezionato al rilascio. Seguendo la ricetta di Donelle, se faccio clic nel mezzo del testo, devo fare clic una seconda volta per poterlo modificare. Se faccio clic da qualche parte all'interno del testo anziché all'esterno del testo, molto probabilmente significa che voglio iniziare la modifica anziché sovrascrivere tutto.

Se hai più di una forma, la sua risposta continua a diventare meno complessa della prima. L'usabilità di entrambe le opzioni è controversa in quanto è possibile modificare il modo in cui funzionano entrambe.
thepaulpage

1
@Sergey: potresti voler cambiare la risposta accettata per questa domanda, poiché da allora ci sono state risposte migliori. Non ho intenzione di suggerire il mio, ma potresti;)
Grokys

La domanda ha il tag Silverlight, ma Silverlight non ha la maggior parte degli eventi / nessun tipo di evento di anteprima. Quale soluzione dovrebbe essere usata per Silverlight allora?
Valentin Kuzub,

Link "Perché la concentrazione in WPF è così complicata?" è rotto
Maxence,

1
come detto in un commento su stackoverflow.com/a/2553297/492 di seguito, madprops.org/blog/wpf-textbox-selectall-on-focus è una soluzione facile e conserva il comportamento nouse originale. Ho inserito la registrazione dell'evento nel costruttore perché ho solo un controllo WPF nell'app.
Bloke CAD,

Risposte:


75

Non so perché perda la selezione GotFocusnell'evento.

Ma una soluzione è fare la selezione su GotKeyboardFocuse gli GotMouseCaptureeventi. In questo modo funzionerà sempre.


10
No. Quando si fa clic con il mouse nel mezzo del testo esistente, la selezione viene persa non appena viene rilasciato il pulsante del mouse.
Sergey Aldoukhov,

3
Tuttavia - dopo un secondo clic singolo, seleziona nuovamente tutto il testo ... Non sono sicuro che si tratti di un comportamento previsto dei progettisti WPF, ma l'usabilità non è poi così male. Un'altra differenza rispetto a un singolo gestore GotFocus è che facendo clic su uno spazio vuoto nella TextBox si seleziona tutto.
Sergey Aldoukhov,

3
Anche questa era la mia prima soluzione. Ma ho scoperto che gli utenti sono davvero infastiditi, quando non sono in grado di selezionare il testo usando il mouse, perché ogni volta che fanno clic sull'intero testo viene selezionato ...
Nils

1
Un ulteriore svantaggio di questa soluzione è quando si utilizza il menu "Taglia / Copia / Incolla" di TextBox, l'intero testo viene selezionato quando si seleziona una voce di menu.

@cores So che questo è vecchio, ma qualcuno sa perché nell'evento GotFocus il testo selezionato è perso? Hai ragione sul fatto che funzioni in altri eventi, ma questa è una soluzione perfettamente accettabile nel mio libro.
Feign

210

Lo abbiamo quindi il primo clic seleziona tutto e un altro clic va al cursore (la nostra applicazione è progettata per l'uso su tablet con penne).

Potresti trovarlo utile.

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
Grazie molte per questo. Funziona meravigliosamente e dovrebbe essere la risposta accettata IMHO. Il codice sopra funziona quando TextBox riceve lo stato attivo tramite tastiera o mouse (e apparentemente stilo). +1
Drew Noakes,

5
Ho visto una risposta quasi identica qui social.msdn.microsoft.com/Forums/en-US/wpf/thread/… , funziona anche come mai non utilizza e.OriginalSource, né striscia attraverso l'albero visivo. C'è qualche vantaggio nel fare tutto questo?
Marco Luglio,

1
Funziona alla grande, ma sarebbe perfetto se consentisse ancora la selezione del testo con il mouse. La barra degli indirizzi di Google Chrome è un perfetto esempio del sistema ideale: se l'utente fa clic e rilascia senza trascinare, l'intero testo viene evidenziato. Tuttavia, se l'utente fa clic e trascina, il trascinamento seleziona il testo normalmente senza selezionare tutto. SelectAll si verifica solo al rilascio del mouse . Giocherò e vedrò se posso migliorare questo design.
devios1

2
Un ulteriore svantaggio di questa soluzione è quando si utilizza il menu "Taglia / Copia / Incolla" di TextBox, l'intero testo viene selezionato quando si seleziona una voce di menu.

1
Ho scoperto che un ulteriore test nel SelectAllTextmetodo per textBox.IsFocusedmigliorarlo. Non si desidera selezionare tutto quando GetKeyboardFocusè dovuto alla tabulazione alt nel programma.
Scott Stafford,

164

La risposta di Donnelle funziona meglio, ma dover derivare una nuova classe per usarla è una seccatura.

Invece di farlo, registro i gestori i gestori in App.xaml.cs per tutti i TextBox nell'applicazione. Questo mi permette di usare la risposta di Donnelle con il controllo TextBox standard.

Aggiungi i seguenti metodi al tuo 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
Questa è una soluzione piuttosto interessante, è stata descritta anche da Matt Hamilton anni fa qui: madprops.org/blog/wpf-textbox-selectall-on-focus
Ashley Davis

Ho ricevuto alcuni errori di ortografia in "riceve", "focalizzato"
Nate Zaugg, il

2
Grazie Nate, corretto, anche se a mia difesa vorrei sottolineare che gli errori di ortografia sono stati copiati alla lettera dalla risposta di Donnelle;)
Grokys,

La domanda ha il tag Silverlight, ma Silverlight non ha la maggior parte degli eventi / nessun tipo di evento di anteprima. Quale soluzione dovrebbe essere usata per Silverlight allora? grazie in anticipo
Valentin Kuzub,

4
"L'ortografia focalizzata è molto più comune negli Stati Uniti; tuttavia, l'ortografia focalizzata viene talvolta utilizzata nel Regno Unito e in Canada, ed è particolarmente comune in Australia e Nuova Zelanda." So nyah;)
Donnelle,

85

Questo è piuttosto vecchio, ma mostrerò comunque la mia risposta.

Ho scelto parte della risposta di Donnelle (ho saltato il doppio clic) perché penso che questo sia più naturale. Tuttavia, come Gcores non mi piace la necessità di creare una classe derivata. Ma non mi piace nemmeno il OnStartupmetodo gcores . E ho bisogno di questo su una base "generalmente ma non sempre".

Ho implementato questo come allegato in DependencyPropertymodo da poter impostare local:SelectTextOnFocus.Active = "True"in xaml. Trovo in questo modo il più piacevole.

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

Per la mia funzione "generale ma non sempre" ho impostato questa proprietà Attache su Truein (globale) TextBox Style. In questo modo "selezionare il testo" è sempre "attivo", ma posso disabilitarlo in base alla casella di testo.


8
+1 è molto meglio che impostarlo a livello globale, ed è più "il modo WPF" che derivare da TextBox.
stijn,

3
+1 Accetto con stijn. "Nascondere" il tuo codice in app.cs non è bello per il povero sviluppatore che deve capire perché sta accadendo SelectAllOnFocus. :-) Ho appena inserito questo nella mia classe per TextBoxBehaviors e quindi ho aggiornato il mio stile TextBox di base. Ha funzionato a meraviglia. Saluti
Lee Campbell,

2
@tronda: aggiungi semplicemente uno stile alle risorse usando un TargetType di TextBox. Ti suggerisco di dare un'occhiata a wpftutorial.net/Styles.html
Nils

2
Un altro +1 per la migliore risposta. L'unico problema che ho riscontrato è che il testo è sempre selezionato anche quando utilizzo il pulsante destro del mouse - cosa che faccio frequentemente per modificare il testo tramite il menu contestuale - la soluzione non funziona in questo caso perché seleziona sempre tutto il testo anche se io volevo solo tagliare 1 parola tramite il menu contestuale. Ragazzi, sapete come risolvere questo problema?
user3313608

2
Mi piace questa risposta, ma perché devi estendere DependencyObject? L'ho rimosso e funziona ancora bene.
Fred,

47

Ecco i comportamenti Blend che implementano la soluzione di risposta per la tua convenienza:

Uno per il collegamento a un singolo 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;
        }
    }
}

E uno per il collegamento alla radice di un contenitore contenente più TextBox:

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

Questa è di gran lunga la soluzione migliore e più pulita. Grazie mille per averlo condiviso.
Golvellius,

Sembra davvero bello, ma per qualche motivo interrompe il controllo delle schede ... Qualche idea sul perché?
Marc,

Vorrei usare la tua soluzione. Ma davvero perso ... forse hai un campione?
Juan Pablo Gomez,

Quando fai clic da qualche parte nella casella di testo mentre hai lo stato attivo (immagina di voler spostare il cursore in un altro posto) selezionerà di nuovo Tutto invece di spostare il cursore. È inaspettato Risolto il problema sostituendo GotMouseCapture con MouseDoubleClick che è comune. Grazie a queste ultime soluzioni di MSDN.
norekhov,

1
Non sembra funzionare quando la casella di testo riceve lo stato iniziale tramite FocusManager.FocusedElement. Qualche idea sul perché?
Szx

24

Sebbene questa sia una vecchia domanda, ho appena avuto questo problema ma l'ho risolto utilizzando un comportamento associato, anziché un comportamento di espressione come nella risposta di Sergey. Ciò significa che non ho bisogno di una dipendenza da System.Windows.InteractivityBlend SDK:

public class TextBoxBehavior
{
    public static bool GetSelectAllTextOnFocus(TextBox textBox)
    {
        return (bool)textBox.GetValue(SelectAllTextOnFocusProperty);
    }

    public static void SetSelectAllTextOnFocus(TextBox textBox, bool value)
    {
        textBox.SetValue(SelectAllTextOnFocusProperty, value);
    }

    public static readonly DependencyProperty SelectAllTextOnFocusProperty =
        DependencyProperty.RegisterAttached(
            "SelectAllTextOnFocus",
            typeof (bool),
            typeof (TextBoxBehavior),
            new UIPropertyMetadata(false, OnSelectAllTextOnFocusChanged));

    private static void OnSelectAllTextOnFocusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var textBox = d as TextBox;
        if (textBox == null) return;

        if (e.NewValue is bool == false) return;

        if ((bool) e.NewValue)
        {
            textBox.GotFocus += SelectAll;
            textBox.PreviewMouseDown += IgnoreMouseButton;
        }
        else
        {
            textBox.GotFocus -= SelectAll;
            textBox.PreviewMouseDown -= IgnoreMouseButton;
        }
    }

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

    private static void IgnoreMouseButton(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        var textBox = sender as TextBox;
        if (textBox == null || (!textBox.IsReadOnly && textBox.IsKeyboardFocusWithin)) return;

        e.Handled = true;
        textBox.Focus();
    }
}

Puoi quindi usarlo nel tuo XAML in questo modo:

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

Ho scritto sul blog qui .


Mi piace questo approccio ma i metodi Get / Set non dovrebbero finire in "Proprietà"; Ho dovuto rimuoverlo per ottenere la compilazione del codice dopo aver aggiunto la parte Xaml.
Patrick Quirk,

Molto bello, ha funzionato come previsto. Mi piace perché mi aiuta a tenere separati i problemi di View quando faccio MVVM.
Killnine,

16

Ecco un'ottima soluzione molto semplice su MSDN :

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

Ecco il codice dietro:

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
In sostanza, questa è la stessa soluzione di quella più votata in questo thread. Ma dal momento che due anni prima, ora so dove da @Donnelle lo ha preso in prestito;)
Sergey Aldoukhov

Questa soluzione è sembrata la più semplice e ha funzionato per me. Volevo un sottoinsieme specifico di testo selezionato per impostazione predefinita quando si entra nella casella di testo.
Jack B Agile

10

Penso che funzioni bene:

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

Se desideri implementarlo come metodo di estensione:

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

E nel tuo GotFocusevento:

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

Ho scoperto la soluzione sopra perché diversi mesi fa stavo cercando un modo per focalizzare l'attenzione su un dato UIElement. Ho scoperto il codice qui sotto da qualche parte (il credito è dato qui) e funziona bene. Lo pubblico anche se non è direttamente correlato alla domanda del PO perché dimostra lo stesso modello di utilizzo Dispatcherper lavorare con un 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);
}

Immagino che questo sia il metodo più semplice da implementare. dopo aver creato il metodo di estensione dovrai solo chiamare myTextBox.SelectAllText (). Perché questa risposta non ha ricevuto più punti? perché le altre soluzioni sono molto meglio?
Tono Nam,

2
Eviterei questo metodo perché si basa su una chiamata asincrona da eseguire dopo il gestore MouseUp della casella di testo. Non mi fiderei che questo sia deterministico al 100% e possa portare a comportamenti incoerenti. Anche se è improbabile che accada, preferirei seguire i metodi infallibili sopra.
Rob H

6

Ecco un tentativo di risolvere alcuni dei problemi con altre soluzioni:

  1. L'uso del menu contestuale del tasto destro per tagliare / copiare / incollare seleziona tutto il testo anche se non è stato selezionato tutto.
  2. Quando si ritorna dal menu contestuale del tasto destro, tutto il testo è sempre selezionato.
  3. Quando si ritorna all'applicazione con Alt+ Tab, tutto il testo è sempre selezionato.
  4. Quando si tenta di selezionare solo una parte del testo al primo clic, tutto viene sempre selezionato (diversamente dalla barra degli indirizzi di Google Chrome, ad esempio).

Il codice che ho scritto è configurabile. Si può scegliere su quali azioni il comportamento seleziona tutto dovrebbe avvenire impostando tre campi di sola lettura: SelectOnKeybourdFocus, SelectOnMouseLeftClick, SelectOnMouseRightClick.

L'aspetto negativo di questa soluzione è che è più complesso e lo stato statico è memorizzato. Sembra una brutta lotta con il comportamento predefinito del TextBoxcontrollo. Tuttavia, funziona e tutto il codice è nascosto nella classe del contenitore Proprietà associate.

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

Per collegare la proprietà allegata a a TextBox, tutto ciò che devi fare è aggiungere lo spazio dei nomi xml ( xmlns) della proprietà allegata e quindi usarlo in questo modo:

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

Alcune note su questa soluzione:

  1. Per sovrascrivere il comportamento predefinito di un evento del mouse verso il basso e abilitare la selezione solo una parte del testo al primo clic, tutto il testo viene selezionato sull'evento del mouse verso l'alto.
  2. Ho dovuto affrontare il fatto che TextBoxricorda la sua selezione dopo aver perso la concentrazione. In realtà ho ignorato questo comportamento.
  3. Ho dovuto ricordare se un pulsante del mouse verso il basso è la prima azione sul TextBox( FirstActionIsMouseDowncampo statico).
  4. Ho dovuto ricordare il menu contestuale aperto con un clic destro ( ContextMenucampo statico).

L'unico effetto collaterale che ho riscontrato è quando SelectOnMouseRightClickè vero. A volte il menu contestuale del tasto destro lampeggia quando viene aperto e facendo clic con il tasto destro del mouse su uno spazio vuoto TextBoxnon fa "selezionare tutto".


5

Non ho trovato nessuna delle risposte qui presentate imitare una casella di testo standard di Windows. Ad esempio, prova a fare clic nello spazio bianco tra l'ultimo carattere della casella di testo e il lato destro della casella di testo. La maggior parte delle soluzioni qui selezionerà sempre l'intero contenuto, il che rende molto difficile aggiungere testo a una casella di testo.

La risposta che presento qui si comporta meglio in questo senso. È un comportamento (quindi richiede l' assembly System.Windows.Interactivity dall'SDK di Blend ). Potrebbe essere riscritto usando anche le proprietà associate.

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

Questo si basa sul codice che ho trovato qui .


1
Sebbene questa sia una buona risposta, penso che quando l'utente fa clic sullo spazio bianco la sua intenzione (in un'applicazione aziendale) è molto probabilmente quella di sovrascrivere l'intero valore, quindi selezionare tutto è l'approccio giusto.
Sergey Aldoukhov,

1
Sergey: il primo clic selezionerà l'intero valore, il secondo clic posizionerà il cursore a destra del valore. Nelle altre soluzioni presentate, il secondo clic manterrà l'intero valore selezionato, rendendo molto difficile l'aggiunta al valore.
Kristof Verbiest,

Come viene usato? Ho aggiunto questo codice ad App.xaml.cs ma non sembra avere effetto sui TextBox nella mia app.
PIntag

5

Questa semplice implementazione funziona perfettamente per me:

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

Per applicarlo a tutti TextBox, inserisci il seguente codiceInitializeComponent();

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

4

Nel file App.xaml:

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

Nel file App.xaml.cs:

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

Con questo codice raggiungi tutto TextBoxnella tua applicazione.


3

Tratto da qui :

Registrare il gestore eventi globale nel file App.xaml.cs:

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

    base.OnStartup(e);
}

Quindi il gestore è semplice come:

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

3

Mi rendo conto che questo è molto vecchio, ma ecco la mia soluzione che si basa sugli spazi dei nomi di interazioni / interazioni espressioni / microsoft.

Innanzitutto, ho seguito le istruzioni di questo link per posizionare i trigger di interattività in uno stile.

Quindi arriva a questo

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

e questo

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

Nel mio caso, ho un controllo utente in cui sono le caselle di testo che ha un code-behind. Il code-behind ha la funzione di gestore. Ho dato al mio controllo utente un nome in XAML e sto usando quel nome per l'elemento. Questo funziona perfettamente per me. Basta applicare lo stile a qualsiasiTextBox cui si desidera selezionare tutto il testo quando si fa clic su TextBox.

Il primo CallMethodActionchiama il SelectAllmetodo della casella di testo quando ilGotKeyboardFocus evento viene TextBoxgenerato.

Spero che aiuti.


Poiché si tratta di domande così vecchie, potrebbe essere utile che la tua risposta attiri l'attenzione se dici perché qualcuno potrebbe scegliere questo approccio.
divibisan,

Prima di tutto, questo non deve essere messo in uno stile, ma penso che sia ovvio che ci sono molti controlli per caselle di testo che ne hanno bisogno, uno stile è la strada da percorrere.
wiyosaya,

1
Forse alcuni non saranno d'accordo con questo approccio, tuttavia, sul motivo per cui potresti utilizzare questo approccio, non richiede la sottoclasse di TextBox, la registrazione di eventi del gestore di classe, i metodi di estensione, la creazione di proprietà associate, ecc. Come stile, potrebbe anche essere aggiunto al dizionario delle risorse di qualsiasi progetto xaml. Senza la chiave x:, verrebbe applicato a qualsiasi istanza TextBox nell'ambito del dizionario delle risorse senza dover modificare lo xaml di ogni singola casella di testo. In alcuni casi, potrebbe essere un approccio più pulito.
wiyosaya,

2

Ho usato la risposta di Nils ma mi sono convertito in più flessibile.

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

In XAML, puoi usare come uno di questi:

<!-- 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
Ottima soluzione per l'uso nei template poiché puoi associarlo a xaml senza alcun codice reale, solo un comportamento esteso della casella di testo.
Eric Johansson,

2

Ecco la versione C # della risposta pubblicata da @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);
}

mentre MyTextBox_GotFocusè il gestore eventi assegnato GotFocusall'evento di MyTextBox.


2

Ho una risposta leggermente semplificata per questo (con solo il PreviewMouseLeftButtonDown evento) che sembra imitare la solita funzionalità di un browser:

In XAML hai TextBoxvoce in capitolo:

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

Nel codebehind:

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
Potrebbe voler aggiungere un evento GotKeyboardFocus con TextBox.SelectAll () all'interno per le persone che si muovono all'interno dell'applicazione. La tua soluzione funziona anche con PasswordBox (poiché le PasswordBox sono tipi sigillati che non possono essere estesi).
David Sherret,

1

Prova questo metodo di estensione per aggiungere il comportamento desiderato a qualsiasi controllo TextBox. Non l'ho ancora ampiamente testato, ma sembra soddisfare i miei bisogni.

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

Ho cercato molto la soluzione, ho trovato un paio di soluzioni da selezionare tutte, ma il problema è quando facciamo clic con il pulsante destro del mouse e tagliamo / copiamo dopo aver selezionato parte del testo dalla casella di testo, seleziona tutto anche se ho selezionato parte del testo. Per risolvere questo problema ecco la soluzione. Basta aggiungere il codice seguente nell'evento di selezione della tastiera. Questo ha funzionato per me.

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

Ho avuto lo stesso problema. In VB.Net funziona in questo modo:

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

La migliore soluzione per me, ho postato traduzione C # qui: stackoverflow.com/a/48385409/3936440
ViRuSTriNiTy

Per me, questo approccio occasionalmente non riesce a selezionare il testo. Penso che siano le condizioni di gara a causa di BeginInvoke.
Vimes,

Per favore specificare. La priorità del dispatcher funziona su applicazioni predefinite come previsto. Qual è la tua situazione? Hai provato esattamente come descritto? Qualcosa di speciale nella tua soluzione?
Nasenbaer,

1

Questa è di gran lunga la soluzione più semplice.

Aggiungi un gestore globale all'applicazione (App.xaml.cs) e fatto. Ti serviranno solo poche righe di codice.

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

    base.OnStartup(e);
}

Quindi utilizzare la classe EventManager per registrare un gestore eventi globale rispetto a un tipo (TextBox). Il gestore effettivo è semplicissimo:

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

Controlla qui: WPF TextBox Select All on Focus

Spero che sia d'aiuto.


1

Per coloro che sono interessati all'approccio di Donnelle / Groky, ma vogliono un clic a destra dell'ultimo carattere (ma ancora all'interno del TextBox) per posizionare il cursore alla fine del testo inserito, ho trovato questa soluzione:

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

Il GetRoundedCharacterIndexFromPointmetodo è stato preso da questo post.


1
Funziona bene, ma l'evento doppio clic non viene attivato
Rodrigo Caballero,

In realtà accede all'evento doppio clic ma la proprietà OriginalSource è di tipo TextBoxView. Quindi il metodo SelectAllText dovrebbe essere così: void statico privato SelectAllText (mittente oggetto, RoutedEventArgs e) {var textBox = e.OriginalSource come TextBox; if (textBox! = null) {textBox.SelectAll (); System.Diagnostics.Debug.WriteLine ("Selected ALL"); } else if (mittente è TextBox) {(mittente come TextBox) .SelectAll (); }
Rodrigo Caballero,

1

Dopo aver cercato su Google e testato, ho trovato una soluzione semplice che ha funzionato per me.

È necessario aggiungere un gestore eventi Loadedall'evento della finestra del contenitore:

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

Successivamente, è necessario creare il gestore per il riferimento RoutedEventHandlernel codice precedente:

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

Ora puoi aggiungere il SelectAll()comando sui GotFocusgestori di eventi a qualsiasi TextBoxcontrollo separatamente:

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

Il tuo testo ora è selezionato in primo piano!

Adattato dalla soluzione Dr. WPF, Forum MSDN


Ho appena usato: vuoto asincrono privato TBTime_GotFocus (mittente oggetto, RoutedEventArgs e) {TextBox tb = (TextBox) e.OriginalSource; await 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

Se hai 20 caselle di testo su una finestra, creerai 3 metodi per ogni casella di testo? Questo approccio non è buono. Dai un'occhiata qui: rachel53461.wordpress.com/2011/11/05/…
Alexandru Dicu

0

Questo sembra funzionare bene per me. Fondamentalmente è un riepilogo di alcuni post precedenti. Ho appena inserito questo nel mio file MainWindow.xaml.cs nel costruttore. Creo due gestori, uno per la tastiera e uno per il mouse, e incanalare entrambi gli eventi nella stessa funzione HandleGotFocusEvent, che è definita subito dopo il costruttore nello stesso file.

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

Bello e facile, ma sembra avere un problema di temporizzazione - ogni altro tentativo (clic del mouse), si deseleziona di nuovo immediatamente ...?
T4NK3R,

0

Un modo semplice per ignorare il mouse verso il basso e selezionare tutto dopo il doppio clic è:

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

Prova a metterlo nel costruttore di qualunque controllo alloggia la tua casella di testo:

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

Questo approccio non funziona quando lo metti in un costruttore di finestre.
ViRuSTriNiTy

0

Se c'è un evento che deseleziona il testo durante il passaggio del OnFocusmouse in su, di solito rimando il seleziona tutto.

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

-1

Li ho testati tutti ma solo i seguenti hanno funzionato:

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
Questo è anche un osceno abuso di codici hash. Lo leggerei, link
RichK,

3
E usare al GetType().Nameposto di iso asè piuttosto
confuso

-1

Vedo che ci sono molte risposte, ma come quella approvata, i metodi che dovrebbero essere usati sono EditTextBoxGotCapture

con il seguente codice dietro:

private void EditTextBoxGotCapture(object sender, MouseEventArgs e)
{
    if (sender is TextBox tb)
    {
        tb.Select(0, tb.Text.Length);
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.