Tengo un formulario que contiene un TextBox
en C # que configuré en una cadena de la siguiente manera:
textBox.Text = str;
Cuando se muestra el formulario, ¿por qué el texto en el cuadro de texto aparece resaltado / seleccionado?
Tengo un formulario que contiene un TextBox
en C # que configuré en una cadena de la siguiente manera:
textBox.Text = str;
Cuando se muestra el formulario, ¿por qué el texto en el cuadro de texto aparece resaltado / seleccionado?
Respuestas:
El cuadro de texto tiene un valor TabIndex
de 0 y se TabStop
establece en verdadero. Esto significa que se le dará foco al control cuando se muestre el formulario.
Puede darle a otro control el 0 TabIndex
(si hay uno) y darle al cuadro de texto un índice de pestaña diferente (> 0), o establecer TabStop
en falso para que el cuadro de texto evite que esto suceda.
El comportamiento predeterminado de un TextBox en Windows Forms es resaltar todo el texto si se enfoca por primera vez al tabularlo, pero no si se hace clic en él. Podemos ver esto en el reflector mirando el TextBox
's OnGotFocus()
de anulación:
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 esa declaración if la que está causando el comportamiento que no nos gusta. Además, para colmo de males, el Text
autor de la propiedad restablece ciegamente esa selectionSet
variable cada vez que se reasigna el texto:
public override string Text
{
get
{
return base.Text;
}
set
{
base.Text = value;
this.selectionSet = false;
}
}
Entonces, si tiene un TextBox y una pestaña en él, se seleccionará todo el texto. Si hace clic en él, se elimina el resaltado y, si vuelve a tabular, se conserva la posición del cursor (y la longitud de selección de cero). Pero si configuramos programáticamente nuevo Text
, y volvemos a tabular en el TextBox, entonces todo el texto se seleccionará nuevamente.
Si usted es como yo y encuentra este comportamiento molesto e inconsistente, entonces hay dos formas de solucionar este problema.
El primero, y probablemente el más fácil, es simplemente activar la configuración de selectionSet
llamando DeselectAll()
al formulario Load()
y siempre que los Text
cambios:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.textBox2.SelectionStart = this.textBox2.Text.Length;
this.textBox2.DeselectAll();
}
( DeselectAll()
Sólo conjuntos SelectionLength
a cero. En realidad es SelectionStart
que voltea la TextBox
's selectionSet
variables. En el caso anterior, el llamado a DeselectAll()
no es necesaria, ya que estamos estableciendo el principio hasta el final del texto. Pero si lo ponemos a cualquier otra posición, al igual el comienzo del texto, luego llamarlo es una buena idea).
La forma más permanente es crear nuestro propio TextBox con el comportamiento deseado a través de la herencia:
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;
}
}
}
Quizás tenga la tentación de no llamar base.OnGotFocus()
, pero entonces perderíamos funcionalidad útil en la Control
clase base . Y es posible que tenga la tentación de no meterse con las selectionSet
tonterías en absoluto y simplemente anular la selección del texto cada vez en OnGotFocus (), pero luego perderíamos el resaltado del usuario si saliera del campo y regresara.
¿Feo? Puedes apostar. Pero es lo que es.
Las respuestas a esta pregunta me ayudaron mucho con un problema similar, pero la respuesta simple solo se insinúa con muchas otras sugerencias complejas. Sólo hay que establecer SelectionStart
que 0
después de ajustar el texto. ¡Problema resuelto!
Ejemplo:
yourtextbox.Text = "asdf";
yourtextbox.SelectionStart = 0;
También puede elegir el orden de las pestañas para los controles de su formulario abriendo:
Ver-> Orden de tabulación
Tenga en cuenta que esta opción solo está disponible en "Ver" si tiene abierta la vista Diseño de formulario.
Al seleccionar "Orden de tabulación" se abre una vista del formulario que le permite elegir el orden de tabulación deseado haciendo clic en los controles.
Para quitar el resaltado de un campo de texto, con VS 2013, intente init con:
myTextBox.GotFocus += new System.EventHandler(this.myTextBox_GotFocus);
Y agregue el método:
public void myTextBox_GotFocus(object sender, EventArgs e)
{
myTextBox.SelectionLength=0;
}
No he probado esto en C # pero encontré el mismo problema usando un cuadro de diálogo C ++ WIN32. Parece que puedes cambiar el comportamiento volviendo FALSE
de OnInitDialog()
o WM_INITDIALOG
. Espero que esto ayude.