98 votes

C #: pourquoi le texte dans la zone de texte est-il mis en surbrillance (sélectionné) lorsque le formulaire est affiché?

J'ai un formulaire contenant une zone de texte en C # que j'ai définie comme une chaîne comme suit:

 textBox.Text = str;
 

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

146voto

fletcher Points 5739

Les TabIndex de 0 et TabStop texte sont définis sur true. Cela signifie que le contrôle sera mis en évidence lorsque le formulaire est affiché.

Vous pouvez soit donner à un autre contrôle les 0 TabIndex (s'il en existe un) et attribuer à la zone de texte un index de tabulation différent (> 0), ou définir TabStop sur false pour la zone de texte. pour empêcher cela de se produire.

48voto

Nicholas Piasecki Points 13681

Le comportement par défaut d'une zone de texte dans les Windows Forms est pour mettre en surbrillance le texte si il est porté pour la première fois en surbrillance, mais pas si il est cliqué. Nous pouvons voir cela dans un Réflecteur en regardant l' TextBoxs' OnGotFocus() remplacer:

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 que, si l'instruction qui est à l'origine du comportement que nous n'aimons pas. En outre, pour ajouter l'insulte à l'injure, l' Text de la propriété de définition de la aveuglément réinitialise qu' selectionSet variable à chaque fois que le texte est attribué à nouveau:

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

Donc, si vous avez une zone de texte et onglet en elle, tous les textes seront sélectionnés. Si vous cliquez sur, le point culminant est retiré, et si vous re-onglet dans, votre position du curseur (et de sélection de longueur zéro) est préservée. Mais si nous définir par programmation de nouveaux Text, et un onglet dans la zone de texte nouveau, puis tout le texte sera sélectionné à nouveau.

Si vous êtes comme moi et de trouver ce comportement gênant et incohérente, puis il y a deux façons de contourner ce problème.

Le premier, et probablement le plus simple, c'est simplement de déclencher le réglage de l' selectionSet en appelant DeselectAll() sur le formulaire Load() et à chaque fois que l' Text changements:

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

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

(DeselectAll() seulement des ensembles SelectionLength à zéro. C'est en fait SelectionStart qui permet d'inverser la TextBoxs' selectionSet variable. Dans le cas ci-dessus, l'appel à l' DeselectAll() n'est pas nécessaire car nous réglage du début à la fin du texte. Mais si nous avons choisi de toute autre position, comme le début du texte, puis de l'appel, c'est une bonne idée.)

La manière plus permanente est de créer notre propre zone de texte avec le comportement souhaité par le biais de l'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 avez peut-être tenté de tout simplement pas appeler base.OnGotFocus(), mais nous perdre de fonctionnalité utile dans la base Control classe. Et vous pourriez être tenté de ne pas toucher à l' selectionSet non-sens, et il suffit de désélectionner le texte à chaque fois, dans OnGotFocus(), mais alors nous perdrions l'utilisateur de mettre en évidence des onglets en dehors du terrain et à l'arrière.

Laid? Vous betcha. Mais elle est ce qu'elle est.

35voto

Frank T. Clark Points 31

Les réponses à cette question m'ont beaucoup aidé avec un problème similaire mais la réponse simple n'est qu'indiquée avec 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;

4voto

BenSmith Points 4956

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

Affichage-> Ordre de tabulation

Notez que cette option est uniquement disponible dans "Affichage" si la vue Conception 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 commandes.

0voto

user3658040 Points 1

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 puissiez changer le comportement en renvoyant FALSE de OnInitDialog () ou WM_INITDIALOG. J'espère que cela t'aides.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X