Question Pourquoi le texte dans la zone de texte est-il en surbrillance (sélectionné) lorsque le formulaire est affiché?


J'ai un formulaire contenant une zone de texte en C # que je mets à une chaîne comme suit:

textBox.Text = str;

Lorsque le formulaire est affiché, pourquoi le texte de la texbox apparaît-il en surbrillance / sélectionné?


66
2017-08-06 06:26


origine


Réponses:


La zone de texte a un TabIndex de 0 et TabStop mis à vrai. Cela signifie que le contrôle sera mis en évidence lorsque le formulaire est affiché.

Vous pouvez soit donner un autre contrôle le 0 TabIndex (s'il y en a un) et attribuez à la zone de texte un index de tabulation différent (> 0) ou définissez TabStop à false pour la zone de texte pour empêcher que cela se produise.


95
2017-08-06 06:36



Le comportement par défaut d'une zone de texte dans Windows Forms consiste à mettre en évidence tout le texte s'il est focalisé pour la première fois en y insérant une tabulation, mais pas s'il est cliqué dessus. Nous pouvons voir cela dans Reflector en regardant le TextBox's OnGotFocus() passer outre:

protected override void OnGotFocus(EventArgs e)
{
    base.OnGotFocus(e);
    if (!this.selectionSet)
    {
        this.selectionSet = true;
        if ((this.SelectionLength == 0) && (Control.MouseButtons == MouseButtons.None))
        {
            base.SelectAll();
        }
    }
}

C'est cela si déclaration qui provoque le comportement que nous n'aimons pas. En outre, pour ajouter l'insulte à la blessure, le Text setter de propriété réinitialise aveuglément que selectionSet variable chaque fois que le texte est réaffecté:

public override string Text
{
    get
    {
        return base.Text;
    }
    set
    {
        base.Text = value;
        this.selectionSet = false;
    }
}

Donc, si vous avez un TextBox et un onglet, tout le texte sera sélectionné. Si vous cliquez dessus, la surbrillance est supprimée et, si vous y renoncez, la position du curseur (et la longueur de sélection de zéro) sont conservées. Mais si nous définissons par programme de nouvelles Text, et onglet dans la zone de texte à nouveau, alors tout le texte sera sélectionné à nouveau.

Si vous êtes comme moi et trouvez ce comportement agaçant et incohérent, il existe deux manières de résoudre ce problème.

Le premier, et probablement le plus facile, consiste simplement à déclencher le réglage de selectionSet en appelant DeselectAll() sur la forme Load() et chaque fois que le Text changements:

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);

    this.textBox2.SelectionStart = this.textBox2.Text.Length;
    this.textBox2.DeselectAll();
}

(DeselectAll() juste définit SelectionLength à zéro. C'est en fait SelectionStart qui retourne le TextBox's selectionSet variable. Dans le cas ci-dessus, l'appel à DeselectAll() n'est pas nécessaire car nous mettons le début à la fin du texte. Mais si on le place dans une autre position, comme le début du texte, l'appel est une bonne idée.)

Le moyen le plus permanent est de créer notre propre TextBox avec le comportement souhaité par héritage:

public class NonSelectingTextBox : TextBox
{
    // Base class has a selectionSet property, but its private.
    // We need to shadow with our own variable. If true, this means
    // "don't mess with the selection, the user did it."
    private bool selectionSet;

    protected override void OnGotFocus(EventArgs e)
    {
        bool needToDeselect = false;

        // We don't want to avoid calling the base implementation
        // completely. We mirror the logic that we are trying to avoid;
        // if the base implementation will select all of the text, we
        // set a boolean.
        if (!this.selectionSet)
        {
            this.selectionSet = true;

            if ((this.SelectionLength == 0) && 
                (Control.MouseButtons == MouseButtons.None))
            {
                needToDeselect = true;
            }
        }

        // Call the base implementation
        base.OnGotFocus(e);

        // Did we notice that the text was selected automatically? Let's
        // de-select it and put the caret at the end.
        if (needToDeselect)
        {
            this.SelectionStart = this.Text.Length;
            this.DeselectAll();
        }
    }

    public override string Text
    {
        get
        {
            return base.Text;
        }
        set
        {
            base.Text = value;

            // Update our copy of the variable since the
            // base implementation will have flipped its back.
            this.selectionSet = false;
        }
    }
}

Vous êtes peut-être tenté de ne pas appeler base.OnGotFocus(), mais alors nous perdrions des fonctionnalités utiles dans la base Control classe. Et vous pourriez être tenté de ne pas jouer avec le selectionSet des absurdités du tout et simplement désélectionner le texte à chaque fois dans OnGotFocus (), mais alors nous perdrions le surlignage de l'utilisateur s'il sortait du champ et revenait en arrière.

Laid? Vous pariez. Mais c'est ce que c'est.


41
2017-08-21 13:35



Les réponses à cette question m'ont beaucoup aidé avec un problème similaire, mais la réponse simple n'est qu'indiquée par beaucoup d'autres suggestions complexes. Il suffit de définir SelectionStart sur 0 après avoir défini votre texte. Problème résolu!

Exemple:

yourtextbox.Text = "asdf";
yourtextbox.SelectionStart = 0;

25
2018-02-26 15:44



Vous pouvez également choisir l'ordre de tabulation pour les contrôles de votre formulaire en ouvrant:

Affichage-> Onglet Ordre

Notez que cette option est uniquement disponible dans "Affichage" si la vue Création de formulaire est ouverte.

La sélection de "Ordre de tabulation" ouvre une vue du formulaire qui vous permet de choisir l'ordre de tabulation souhaité en cliquant sur les contrôles.


3
2018-04-11 11:11



Pour mettre en évidence un champ de texte, avec VS 2013, essayez init avec:

myTextBox.GotFocus += new System.EventHandler(this.myTextBox_GotFocus);

Et ajoutez la méthode:

public void myTextBox_GotFocus(object sender, EventArgs e)
{
    myTextBox.SelectionLength=0;
}

1
2018-06-03 12:34



Je n'ai pas testé cela sur C # mais j'ai rencontré le même problème en utilisant une boîte de dialogue C ++ WIN32. Il semble que vous pouvez modifier le comportement en renvoyant FALSE à partir de OnInitDialog () ou WM_INITDIALOG. J'espère que cela t'aides.


0
2018-05-20 19:17