Ich habe ein Formular mit einem TextBox
in 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?
Ich habe ein Formular mit einem TextBox
in 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?
Antworten:
Das Textfeld hat eine TabIndex
0 und wird TabStop
auf 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 TabStop
für das Textfeld den Wert false festlegen , um dies zu verhindern.
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 Text
Setter der Eigenschaft diese selectionSet
Variable 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 Text
festlegen 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 selectionSet
durch 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 SelectionLength
auf Null. SelectionStart
Tatsächlich wird die Variable von TextBox
' selectionSet
umgedreht. 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 selectionSet
Unsinn 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.
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
, 0
nachdem Sie Ihren Text eingestellt haben. Problem gelöst!
Beispiel:
yourtextbox.Text = "asdf";
yourtextbox.SelectionStart = 0;
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.
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;
}
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 FALSE
von OnInitDialog()
oder zurückkehren WM_INITDIALOG
. Hoffe das hilft.