2010-08-06 23 views
63

Tengo un formulario que contiene un cuadro de texto en C#, la cual di a una cadena como sigue:¿Por qué el texto en el cuadro de texto está resaltado (seleccionado) cuando se muestra el formulario?

textBox.Text = str; 

Cuando se muestra el formulario, ¿por qué el texto en el TexBox aparezca resaltado/seleccionado?

+0

Su pregunta podría estar relacionado con http://stackoverflow.com/ questions/1140250/how-to-remove-focus-from-a-textbox-in-c-winforms – DarenW

+0

¿Pudo resolver esto? ¿Cómo arreglaste esto? – fletcher

+0

@fletcher: Todavía no he podido verlo. Voy a otorgar la respuesta en unos días. – CJ7

Respuesta

87

El cuadro de texto tiene un TabIndex de 0 y TabStop establecido en verdadero. Esto significa que el control se enfocará cuando se muestre el formulario.

Puede otorgar otro control al 0 TabIndex (si lo hay) y darle al cuadro de texto un índice de pestaña diferente (> 0) o establecer TabStop en falso para que el cuadro de texto detenga esto.

+1

¿Estás seguro de que el cuadro de texto TabIndex está establecido en 0? Viene de su comportamiento? – 26071986

+0

@ 26071986 - Bueno, realicé una prueba rápida. Si, en un formulario con un cuadro de texto y un botón, cambio el texto dentro del cuadro de texto en el constructor cuando el tabindex se establece en 0, el texto se resalta. Si el botón tiene el índice de 0 pestañas y el tabindex de la caja de texto es> 0, el texto no está resaltado. – fletcher

+0

Eso es interesante ... – 26071986

38

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 Reflector examinado OnGotFocus() anulación del TextBox 's:

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 que si la declaración que está causando el comportamiento que no nos gusta. Además, para colmo de males, organismo de la propiedad Text restablece ciegamente que selectionSet variables cada vez que se presenta el texto re-asignado:

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

Así que si usted tiene un cuadro de texto y pestaña en ella, se seleccionará todo el texto. Si hace clic en él, se eliminará el resaltado y, si vuelve a tabular en él, se conservará su posición de intercalación (y la longitud de selección de cero). Pero si configuramos programáticamente el nuevo Text, y tabulamos en el TextBox de nuevo, todo el texto se volverá a seleccionar.

Si eres como yo y encuentras este comportamiento molesto e incoherente, entonces hay dos formas de solucionar este problema.

La primera, y probablemente el más fácil, es simplemente activar la configuración de selectionSet llamando DeselectAll() en forma 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() simplemente establece SelectionLength a cero En realidad es SelectionStart que invierte la variable TextBoxselectionSet. En el caso anterior, la llamada a DeselectAll() no es necesaria ya que estamos configurando el inicio hasta el final del texto. Pero si lo configuramos en cualquier otra posición, como el comienzo del texto , luego llamando es una buena idea)

La forma más permanente es crear nuestro propio cuadro de texto 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; 
     } 
    } 
} 

Usted tal vez la tentación de no llamar base.OnGotFocus(), pero entonces perdería útil funcionalidad en la clase base Control. Y es posible que tenga la tentación de no meterse con el absurdo selectionSet en absoluto y simplemente anule la selección del texto cada vez que lo haga en OnGotFocus(), pero luego perderíamos el resaltado del usuario si saltaran del campo y retrocedieran.

¿Ugly? Puedes apostar. Pero es lo que es.

22

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. Simplemente configure SelectionStart en 0 después de configurar su texto. ¡Problema resuelto!

Ejemplo:

yourtextbox.Text = "asdf"; 
yourtextbox.SelectionStart = 0; 
3

También puede elegir el orden de tabulación de los controles del formulario mediante la apertura:

Ver-> Orden de tabulación

Tenga en cuenta que esta opción sólo está disponible en " Ver "si tiene abierta la vista de 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.

+1

Esto me ayudó mucho. En realidad, el índice de pestañas no importa si nos ocupamos del orden de las pestañas. –

0

No he probado esto en C# pero me encontré con el mismo problema usando un cuadro de diálogo C++ WIN32. Parece que puede cambiar el comportamiento devolviendo FALSE desde OnInitDialog() o WM_INITDIALOG. Espero que esto ayude.

+1

No creo que esto ayude mucho, ya que la API de Windows está encapsulada en winforms. –

1

Para eliminar el realce de un campo de texto, con VS 2013, tratan con init:

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

y añadir el método:

public void myTextBox_GotFocus(object sender, EventArgs e) 
{ 
    myTextBox.SelectionLength=0; 
} 
Cuestiones relacionadas