Ho un modulo contenente un TextBox
in C # che ho impostato su una stringa come segue:
textBox.Text = str;
Quando viene visualizzato il modulo, perché il testo nel texbox appare evidenziato / selezionato?
Ho un modulo contenente un TextBox
in C # che ho impostato su una stringa come segue:
textBox.Text = str;
Quando viene visualizzato il modulo, perché il testo nel texbox appare evidenziato / selezionato?
Risposte:
La casella di testo ha TabIndex
0 e TabStop
impostata su true. Ciò significa che al controllo verrà assegnato lo stato attivo quando viene visualizzato il modulo.
Puoi dare a un altro controllo lo 0 TabIndex
(se ce n'è uno) e dare alla casella di testo un indice di tabulazione diverso (> 0), oppure impostare TabStop
su false affinché la casella di testo impedisca che ciò accada.
Il comportamento predefinito di una casella di testo in Windows Forms consiste nell'evidenziare tutto il testo se viene messo a fuoco per la prima volta mediante tabulazione, ma non se viene fatto clic su di esso. Possiamo vedere questo in Reflector, cercando in la TextBox
's OnGotFocus()
di override:
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();
}
}
}
È quella dichiarazione if che sta causando il comportamento che non ci piace. Inoltre, per aggiungere la beffa al danno, il Text
setter della proprietà resetta ciecamente quella selectionSet
variabile ogni volta che il testo viene riassegnato:
public override string Text
{
get
{
return base.Text;
}
set
{
base.Text = value;
this.selectionSet = false;
}
}
Quindi, se hai una casella di testo e una scheda in essa, tutto il testo verrà selezionato. Se fai clic su di esso, l'evidenziazione viene rimossa e, se ci si reimposta, la posizione del cursore (e la lunghezza della selezione pari a zero) viene preservata. Ma se impostiamo di nuovo a livello Text
di codice new e tab nella casella di testo, tutto il testo verrà selezionato di nuovo.
Se sei come me e trovi questo comportamento fastidioso e incoerente, allora ci sono due modi per aggirare questo problema.
Il primo, e probabilmente il più semplice, è semplicemente attivare l'impostazione di selectionSet
richiamando DeselectAll()
il modulo Load()
e ogni volta che le Text
modifiche:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.textBox2.SelectionStart = this.textBox2.Text.Length;
this.textBox2.DeselectAll();
}
( DeselectAll()
Solo set SelectionLength
a zero. In realtà SelectionStart
che ribalta il TextBox
's selectionSet
variabile. Nel caso di cui sopra, la chiamata a DeselectAll()
non è necessario poiché stiamo impostando l'inizio e la fine del testo. Ma se abbiamo impostato a qualsiasi altra posizione, come l'inizio del testo, quindi chiamarlo è una buona idea.)
Il modo più permanente è creare il nostro TextBox con il comportamento desiderato attraverso l'ereditarietà:
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;
}
}
}
Potresti essere tentato di non chiamare base.OnGotFocus()
, ma perderemmo funzionalità utili nella Control
classe base . E potresti essere tentato di non scherzare affatto con le selectionSet
sciocchezze e deselezionare semplicemente il testo ogni volta in OnGotFocus (), ma poi perderemmo l'evidenziazione dell'utente se uscisse dal campo e tornasse indietro.
Brutto? Ci puoi scommettere. Ma è quello che è.
Le risposte a questa domanda mi hanno aiutato molto con un problema simile, ma la risposta semplice è solo accennata con molti altri suggerimenti complessi. Basta impostare SelectionStart
su 0
dopo aver impostato il testo. Problema risolto!
Esempio:
yourtextbox.Text = "asdf";
yourtextbox.SelectionStart = 0;
Puoi anche scegliere l'ordine di tabulazione per i controlli del modulo aprendo:
Visualizza-> Ordine di tabulazione
Nota che questa opzione è disponibile solo in "Visualizza" se hai aperto la vista Struttura modulo.
Selezionando "Tab Order" si apre una visualizzazione del Form che consente di scegliere l'ordine di tabulazione desiderato facendo clic sui controlli.
Per deselezionare un campo di testo, con VS 2013, prova init con:
myTextBox.GotFocus += new System.EventHandler(this.myTextBox_GotFocus);
E aggiungi il metodo:
public void myTextBox_GotFocus(object sender, EventArgs e)
{
myTextBox.SelectionLength=0;
}
Non l'ho testato su C # ma ho riscontrato lo stesso problema utilizzando una finestra di dialogo C ++ WIN32. Sembra che tu possa cambiare il comportamento tornando FALSE
da OnInitDialog()
o WM_INITDIALOG
. Spero che sia di aiuto.