J'ai un formulaire contenant un TextBox
en C # que j'ai défini comme chaîne:
textBox.Text = str;
Quand le formulaire est affiché, pourquoi le texte dans la texbox apparaît-il en surbrillance/sélectionné?
La zone de texte a une valeur TabIndex
égale à 0 et TabStop
définie 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 le 0 TabIndex
(s'il en existe un) et attribuer à la zone de texte un index de tabulation différent (> 0), ou définir TabStop
à false pour que la zone de texte cesse cela se passe.
Le comportement par défaut d'une zone de texte dans Windows Forms consiste à mettre tout le texte en surbrillance s'il est mis en évidence pour la première fois en le faisant défiler, mais pas s'il est cliqué dessus. Nous pouvons le voir dans Reflector en regardant le OnGotFocus()
de TextBox
:
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 la déclaration provoque le comportement que nous n'aimons pas. De plus, pour ajouter de l'insulte à la blessure, l'attribut de la propriété Text
réinitialise aveuglément cette variable selectionSet
à 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 une zone de texte et une tabulation, tout le texte sera sélectionné. Si vous cliquez dessus, la surbrillance est supprimée et si vous la re-tabulez, votre position de curseur (et la longueur de sélection égale à zéro) sont conservées. Mais si nous définissons par programmation new Text
, et que nous plaçons à nouveau dans la zone de texte, tout le texte sera à nouveau sélectionné.
Si vous êtes comme moi et trouvez ce comportement agaçant et incohérent, vous pouvez résoudre ce problème de deux manières.
La première, et probablement la plus simple, consiste simplement à déclencher le réglage de selectionSet
en appelant DeselectAll()
sur le formulaire Load()
et à chaque fois que le Text
change:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.textBox2.SelectionStart = this.textBox2.Text.Length;
this.textBox2.DeselectAll();
}
(DeselectAll()
ne fait que mettre SelectionLength
à zéro. C'est en fait SelectionStart
qui inverse la variable TextBox
de selectionSet
. Dans le cas ci-dessus, la variable L'appel à DeselectAll()
n'est pas nécessaire, car nous définissons le début jusqu'à la fin du texte, mais si nous le positionnons sur une autre position, comme le début du texte, l'appeler est une bonne idée. )
La manière la plus permanente est de créer notre propre zone de texte 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 pourriez être tenté de ne pas simplement appeler base.OnGotFocus()
, mais nous perdrions alors des fonctionnalités utiles dans la classe de base Control
. Et vous pourriez être tenté de ne pas jouer du tout avec le non-sens selectionSet
et simplement de désélectionner le texte à chaque fois dans OnGotFocus (), mais nous perdrions alors le surlignage de l’utilisateur s’ils sortaient du champ et revenaient.
Laid? Vous betcha. Mais c'est ce que c'est.
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;
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 n'est disponible dans "Vue" que 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.
Pour mettre en surbrillance 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;
}
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.