2010-12-16 8 views
6

Tengo una aplicación WinForm con varios controles de entrada en un formulario. En el controlador de eventos de validación (Validating o Validated), necesito determinar qué control activar a continuación, en función del valor validado.Cómo establecer el foco en un control después de la validación en .NET

En la documentación del evento Validating de Microsoft, se indica:

Precaución

No intente ajustar el enfoque desde el interior de la Intro, GotFocus, licencia, LostFocus, validar o controladores de eventos validados. Hacerlo puede hacer que su aplicación o el sistema operativo dejen de responder. Para obtener más información, consulte el tema WM_KILLFOCUS en la sección "Referencia de entrada de teclado" y la sección "Interbloqueos de mensajes" del tema "Acerca de mensajes y colas de mensajes" en la biblioteca MSDN en http: // msdn.microsoft.com/library .

Hay un ActiveControl propiedad para una clase de formulario que permite establecer el control que es llegar a ser activo, y se mencionan ninguna restricción. No he encontrado ninguna otra solución después de varias horas de búsquedas web.

Está configurando la propiedad ActiveControl (en lugar de Focus) de mi controlador de eventos Validated una forma segura de activar positivamente el control que quiero? Si no, ¿hay alguna solución?

Como .NET Compact Framework no tiene la propiedad ActiveControl, ¿alguien puede sugerir una solución?

Respuesta

9

Sí, cambiando el enfoque durante un evento de validación es bastante molesto. El evento se levanta en el momento exacto en que cambia el foco. El siguiente control ya ha obtenido el foco en lo que respecta a Windows, pero el estado de forma lógica todavía tiene el foco en el control que se valida. Cuando configura e.Cancel como verdadero, las formas de Winform deben deshacer el estado de foco de Windows. Cuando no lo haga, debe actualizar el estado lógico después del evento. Hay una gran variedad de cosas que pueden salir mal cuando cambia el enfoque usted mismo.

Es importante que espere hasta que se haya resuelto el enfoque. Lo mejor es retrasar el código hasta que todo se termine de ejecutar y el formulario vuelva a estar inactivo. Puedes hacerlo limpiamente usando el método Control.BeginInvoke(). Algo como esto:

private delegate void ChangeFocusDelegate(Control ctl); 

    private void textBox1_Validating(object sender, CancelEventArgs e) { 
     int value; 
     if (!int.TryParse(textBox1.Text, out value)) e.Cancel = true; 
     else { 
      if (value == 1) this.BeginInvoke(new ChangeFocusDelegate(changeFocus), textBox2); 
      else this.BeginInvoke(new ChangeFocusDelegate(changeFocus), textBox3); 
     } 
    } 
    private void changeFocus(Control ctl) { 
     ctl.Focus(); 
    } 
+0

¡Guau, respuesta inteligente! Pensé que el método delegado tenía que llamar a EndInvoke(), pero eso fue antes de saber la diferencia entre Delegate.BeginInvoke() y Control.BeginInvoke(). Ver \t [.net - Cuál es la diferencia entre Invoke() y BeginInvoke] [1] [1] http://stackoverflow.com/questions/229554/whats-the-difference-between-invoke-and-begininvoke – Suncat2000

1

¿Ha intentado establecer el Cancel property del CancelEventArgs que se pasan al controlador de eventos Validating a False?

Esta es la forma prevista de mantener el foco en el control actual y evitar que el próximo control se enfoque si falla la validación. Por ejemplo:

private void TextBox1_Validating(object sender, System.ComponentModel.CancelEventArgs e) 
{ 
    //Make sure that the textbox is not left blank 
    if (string.IsNullOrEmpty(TextBox1.Text)) 
    { 
     e.Cancel = true; 
    } 
} 
+0

Gracias. Sé sobre esto, pero solo evita que el foco cambie. No permite establecer el foco en un control específico. – Suncat2000

+0

@Suncat: Sí, no pude deducir de la pregunta que quería establecer el foco en un control * diferente *. Hans ya te dio una buena respuesta sobre cómo hacerlo. –

0

Este hilo es viejo, pero tengo un par de reflexiones:

  1. Cada control tiene una propiedad Tag.¿Qué tal si le damos el control que desea para enfocar un valor único de Etiqueta, y luego creamos un método que iterará a través de los controles para encontrar ese control? Entonces puedes enfocarlo.

  2. En lugar de utilizar el evento Validating, ¿por qué no utilizar Leaving en su lugar? No parece tener las mismas peculiaridades.

Cuestiones relacionadas