Warum wird Text in TextBox hervorgehoben (ausgewählt), wenn das Formular angezeigt wird?

84

Ich habe ein Formular mit einem TextBoxin C #, das ich wie folgt auf einen String gesetzt habe:

textBox.Text = str;

Warum wird der Text in der Texbox hervorgehoben / ausgewählt angezeigt, wenn das Formular angezeigt wird?

CJ7
quelle
Ihre Frage könnte im Zusammenhang mit stackoverflow.com/questions/1140250/…
DarenW
Hast du es geschafft, das zu klären? Wie haben Sie das behoben?
Fletcher
@fletcher: Ich bin noch nicht dazu gekommen, es mir anzusehen. Ich werde die Antwort in ein paar Tagen vergeben.
CJ7
Sie können ein vb.net-Tag hinzufügen, da das Problem wirklich dasselbe ist und die akzeptierte Antwort auch gültig ist
Andrea Antonangeli
Die Antwort von BenSmith in Bezug auf das Anzeigen der Tab-Reihenfolge ist in einem solchen Szenario sehr nützlich.
Samitha Chathuranga

Antworten:

128

Das Textfeld hat eine TabIndex0 und wird TabStopauf true gesetzt. Dies bedeutet, dass das Steuerelement bei der Anzeige des Formulars den Fokus erhält.

Sie können entweder einem anderen Steuerelement die 0 TabIndex(falls vorhanden) zuweisen und dem Textfeld einen anderen Registerkartenindex (> 0) zuweisen oder TabStopfür das Textfeld den Wert false festlegen , um dies zu verhindern.

Fletcher
quelle
1
Sind Sie sicher, dass das Textfeld TabIndex auf 0 gesetzt ist? Es kommt aus seinem Verhalten?
26071986
@ 26071986 - Nun, ich habe einen Schnelltest durchgeführt. Wenn ich in einem Formular mit einem Textfeld und einer Schaltfläche den Text innerhalb des Textfelds im Konstruktor ändere, wenn der Tabindex auf 0 gesetzt ist, wird der Text hervorgehoben. Wenn die Schaltfläche den Index der Registerkarte 0 hat und der Textfeld-Tabindex> 0 ist, wird der Text nicht hervorgehoben.
Fletcher
Es scheint tatsächlich mit TabIndex zu tun zu haben - nur ich habe alle Registerkartenindizes meiner Elemente entsprechend geändert (so dachte ich). Es stellt sich heraus, dass Gruppen auch Registerkartenindizes haben, die Sie ändern müssen, sowie alle ihre enthaltenen Elemente. Während ich Elementregisterkarten von 1 bis 9 eingerichtet hatte, hatte eine Gruppe immer noch 0, sodass das Textfeld in dieser Gruppe das erste aktivierte Element wurde (daher wurde dessen Inhalt hervorgehoben).
deed02392
1
Es hängt nicht unbedingt mit TabIndex = 0 zusammen, aber es kommt sicherlich vor, wenn die TextBox den NIEDRIGSTEN TabIndex des Formulars hat. So überprüfen Sie Folgendes: Setzen Sie in der Textbox TabIndex = 5 und in allen TabIndexs der anderen Steuerelemente des Formulars eine Zahl größer als 5.
Andrea Antonangeli
Dies geschieht auch, wenn Sie eine neue TabPage in einem TabControl auswählen. Die gleiche Lösung funktioniert.
JonP
43

Das Standardverhalten einer TextBox in Windows Forms besteht darin, den gesamten Text hervorzuheben, wenn er zum ersten Mal durch Tippen darauf fokussiert wird, nicht jedoch, wenn darauf geklickt wird. Wir können dies in Reflector sehen Sie in der Suche TextBox‚s OnGotFocus()überschreiben:

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

Es ist diese if-Anweisung, die das Verhalten verursacht, das wir nicht mögen. Um die Verletzung zusätzlich zu beleidigen, setzt der TextSetter der Eigenschaft diese selectionSetVariable blind zurück, wenn der Text neu zugewiesen wird:

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

Wenn Sie also eine TextBox und eine Registerkarte haben, wird der gesamte Text ausgewählt. Wenn Sie darauf klicken, wird die Hervorhebung entfernt, und wenn Sie erneut darauf klicken, bleibt Ihre Caret-Position (und die Auswahllänge Null) erhalten. Wenn wir jedoch programmgesteuert neu Textfestlegen und erneut in die TextBox wechseln, wird der gesamte Text erneut ausgewählt.

Wenn Sie wie ich sind und dieses Verhalten als störend und inkonsistent empfinden, gibt es zwei Möglichkeiten, um dieses Problem zu umgehen.

Die erste und wahrscheinlich einfachste Möglichkeit besteht darin, die Einstellung einfach selectionSetdurch Aufrufen DeselectAll()des Formulars Load()und bei jeder TextÄnderung auszulösen :

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

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

( DeselectAll()setzt nur SelectionLengthauf Null. SelectionStartTatsächlich wird die Variable von TextBox' selectionSetumgedreht. Im obigen Fall ist der Aufruf von DeselectAll()nicht erforderlich, da wir den Anfang bis zum Ende des Textes setzen. Aber wenn wir ihn auf eine andere Position setzen, wie z Es ist eine gute Idee, den Anfang des Textes zu beginnen und ihn dann aufzurufen.)

Der dauerhaftere Weg besteht darin, eine eigene TextBox mit dem gewünschten Verhalten durch Vererbung zu erstellen:

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

Sie könnten versucht sein, einfach nicht anzurufen base.OnGotFocus(), aber dann würden wir nützliche Funktionen in der Basisklasse verlieren Control. Und Sie könnten versucht sein, sich überhaupt nicht mit dem selectionSetUnsinn herumzuschlagen und den Text jedes Mal in OnGotFocus () abzuwählen, aber dann würden wir die Hervorhebung des Benutzers verlieren, wenn er aus dem Feld und zurück wechselt.

Hässlich? Darauf kannst du wetten. Aber es ist was es ist.

Nicholas Piasecki
quelle
31

Die Antworten auf diese Frage haben mir bei einem ähnlichen Problem sehr geholfen, aber die einfache Antwort wird nur mit vielen anderen komplexen Vorschlägen angedeutet. Einfach einstellenSelectionStart , 0nachdem Sie Ihren Text eingestellt haben. Problem gelöst!

Beispiel:

yourtextbox.Text = "asdf";
yourtextbox.SelectionStart = 0;
Frank T. Clark
quelle
4

Sie können auch die Tabulatorreihenfolge für die Steuerelemente Ihres Formulars auswählen, indem Sie Folgendes öffnen:

Ansicht-> Tab-Reihenfolge

Beachten Sie, dass diese Option in "Ansicht" nur verfügbar ist, wenn Sie die Formularentwurfsansicht geöffnet haben.

Durch Auswahl von "Tab-Reihenfolge" wird eine Ansicht des Formulars geöffnet, in der Sie die gewünschte Tab-Reihenfolge auswählen können, indem Sie auf die Steuerelemente klicken.

Ben Smith
quelle
1
Das hat mir sehr geholfen. Tatsächlich spielt der Tab-Index keine Rolle, wenn es um die Tab-Reihenfolge geht.
Samitha Chathuranga
1

Um ein Textfeld in VS 2013 hervorzuheben, versuchen Sie init mit:

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

Und fügen Sie die Methode hinzu:

public void myTextBox_GotFocus(object sender, EventArgs e)
{
    myTextBox.SelectionLength=0;
}
Marty
quelle
Dies würde dazu führen, dass die Auswahl des Texts aufgehoben wird, wenn Sie zuvor das Textfeld fokussiert, Text darin ausgewählt, von ihm entfernt und dann erneut fokussiert haben.
Stewart
0

Ich habe dies nicht auf C # getestet, aber ich bin über ein C ++ WIN32-Dialogfeld auf dasselbe Problem gestoßen. Es scheint, als könnten Sie das Verhalten ändern, indem Sie FALSEvon OnInitDialog()oder zurückkehren WM_INITDIALOG. Hoffe das hilft.

user3658040
quelle
1
Ich denke nicht, dass dies viel helfen wird, da die Windows-API in Winforms gekapselt ist.
Nathan A