2008-10-02 13 views
10

¿Hay alguna manera para que el formulario principal pueda interceptar eventos que se activan en un subcontrol en un control de usuario?¿Cómo capturo eventos de subcontroles en un control de usuario en una aplicación WinForms?

Tengo un control de usuario personalizado incrustado en el formulario principal de mi aplicación. El control contiene varios subcontroles que manipulan datos, que a su vez se muestran en otros controles en el formulario principal. Lo que me gustaría es si el formulario principal podría estar de alguna manera informado cuando el usuario cambie los subcontroles, por lo que podría actualizar los datos y la pantalla correspondiente en otro lugar.

En este momento, estoy haciendo trampa. Tengo un delegado conectado al evento de dejar foco de los subcontroles. Este delegado cambia una propiedad del control de usuario que no estoy utilizando en otro lugar (en este caso, CausesValidation). Luego tengo un delegado definido en el formulario principal para cuando cambia la propiedad CausesValidation del control de usuario, que luego dirige la aplicación para actualizar los datos y mostrarlos.

Surge un problema porque también tengo un delegado configurado para cuando el foco deja el control de usuario, porque necesito validar los campos en el control de usuario antes de poder permitir al usuario hacer cualquier otra cosa. Sin embargo, si el usuario solo está cambiando entre subcontroles, no quiero validar, porque es posible que no se haya terminado de editar.

Básicamente, deseo que los datos se actualicen cuando el usuario cambie de subconcesion O deje el control del usuario, pero no valide. Cuando el usuario deja el control, quiero actualizar Y validar. En este momento, dejar el control de usuario hace que la validación se active dos veces.

+0

¿Qué hay de malo en vincular el formulario principal a los diversos eventos de los controles? Hay un montón de eventos que disparan para la mayoría de los controles winform – Sekhat

+0

Creo que simplemente no entiendo lo que quieres lograr: P – Sekhat

+0

Para responder la primera pregunta, a través del diseñador (que es lo que yo, siendo relativamente nuevo en C#, estaba usando para la edición de mi GUI), mi formulario solo tiene acceso a los eventos generados por el control del usuario, y no a sus subcontroles. Lo que no recuerdo es que puedo activar mis propios eventos y manejarlos. –

Respuesta

15

La mejor práctica sería exponer eventos en el UserControl que burbujean los eventos hasta el formulario principal. He seguido adelante y he creado un ejemplo para ti. Aquí hay una descripción de lo que ofrece este ejemplo.

  • UserControl1
    • Crear una UserControl con TextBox1
    • El registro de un evento público en el UserControl llamada ControlChanged
    • Dentro del UserControl registrar un controlador de eventos para el TextBox1 TextChangedEvent
    • Dentro del manejador TextChangeEvent función que llamo el ControlChanged caso de la burbuja a la forma original
  • Form1
    • gota una instancia de UserControl1 en el diseñador
    • Registra un controlador de eventos en UserControl1 para MouseLeave y para ControlChanged

Aquí hay una captura de pantalla que ilustra que el evento ControlChanged que definí en el UserControl está disponible a través del UX en Visual Studio en el formulario principal de Windows.

Event Handlers for User Control http://friendfeed.s3.amazonaws.com/0d5a3968cb785625c8afb3974a8d84894c476291

+0

Gracias, esto es lo que terminé haciendo, excepto que en lugar de MouseLeave, utilicé FocusLeave, ya que el error potencial de cada vez que el usuario mueve su mouse podría ser irritante. ¡Además, gracias por revisar todo el trabajo para esto! –

+0

así que si tiene muchos controles diferentes (digamos, un cuadro de texto, un botón, una casilla de verificación y una etiqueta), y todos los eventos apropiados/reales del control se manejan dentro del control de usuario (control de usuario autónomo), y deseaba crear un evento único (por ejemplo, MyControl.OnClick) en el formulario de contenedor, ¿podría "secuestrar" todos los eventos de subcontrol a través de un único método/mecanismo para hacer saltar el evento Click simple, o aún tendría que hacerlo? Conecte manualmente cada evento de subcontrol y controle el burbujeo usted mismo para cada evento. – MaxOvrdrv

+1

El enlace no funciona. El código debe ir como texto en la respuesta, no como un enlace para descargar un archivo zip. – ardila

2

El mejor modelo para este tipo de cosas será crear eventos personalizados en su control de usuario y subirlos en los momentos apropiados.

Su situación es bastante compleja, pero no desconocida. (De hecho, estoy en un modo muy similar en uno de mis proyectos actuales). La forma en que lo abordo es que el control del usuario es responsable de su propia validación. No uso CausesValidation; en cambio, en el punto de control del usuario apropiado, realizo la validación a través de una anulación de ValidateChildren(). (Esto generalmente sucede cuando el usuario hace clic en "Guardar" o "Siguiente" en el control de usuario, para mí.)

No estar familiarizado con su IU de control de usuario, puede que no sea el enfoque 100% adecuado para usted. Sin embargo, si genera eventos personalizados (posiblemente con EventArgs personalizados que especifiquen si realizar o no la validación), debería poder llegar a donde desea estar.

2

Usted tendrá que cablear los eventos que le interesan captura dentro de su control de usuario, y publicar a través de algunas de las propiedades de eventos personalizados en el propio control de usuario. Un ejemplo sencillo sería envolver un evento de clic de botón:

// CustomControl.cs 
// Assumes a Button 'myButton' has been added through the designer 

// we need a delegate definition to type our event 
public delegate void ButtonClickHandler(object sender, EventArgs e); 

// declare the public event that other classes can subscribe to 
public event ButtonClickHandler ButtonClickEvent; 

// wire up the internal button click event to trigger our custom event 
this.myButton.Click += new System.EventHandler(this.myButton_Click); 
public void myButton_Click(object sender, EventArgs e) 
{ 
    if (ButtonClickEvent != null) 
    { 
    ButtonClickEvent(sender, e); 
    } 
} 

Luego, en la forma que utiliza ese control, se cablea el evento como lo haría con cualquier otra:

// CustomForm.cs 
// Assumes a CustomControl 'myCustomControl' has been added through the desinger 
this.myCustomControl.ButtonClickEvent += new System.EventHandler(this.myCustomControl_ButtonClickEvent); 
myCustomControl_ButtonClickEvent(object sender, EventArgs e) 
{ 
    // do something with the newly bubbled event 
} 
+0

Tal vez estoy equivocado o realmente no entiendo la idea, pero ¿no debería haber ' new MyProject.CustomControl.ButtonClickHandler() 'en lugar de' new System.EventHandler() 'en' CustomForm.cs'? – MRM

0

me gustaría sonar en eso, como se describió, realmente suena como si estuvieras persiguiendo una pista falsa. Si bien parece que tienes una situación en la que la falta de eventos burbujeantes en WinForms te está causando problemas, la realidad es que una arquitectura deficiente te está obligando a necesitar el burbujeo del evento cuando no deberías hacerlo.

Si puede refactorizar/reestructurar su diseño de modo que los controles funcionen con un modelo de datos común (MVC/MVP son opciones obvias), simplemente puede aplicar patrones comunes de WinForms como eventos PropertyChanged en el modelo para indicar su forma principal y cualquier otro control que consuma esa información para actualizarse.

En resumen, las otras respuestas son razonables ya que responden la pregunta como se les pidió. Pero desde el punto de vista de la calidad del código, creo que la mejor respuesta es separar sus datos de la IU.

1

En caso de que alguien todavía se esté preguntando cómo simular el evento de borboteo en WinForm, el método Application.AddMessageFilter es un buen lugar para mirar.

Usando este método puede instalar su propio filtro que monitorea todos los mensajes que se publican en la cola de mensajes del hilo actual.

Debe tener en cuenta que los mensajes enviados (no publicados) no pueden ser manejados por este filtro.En última instancia, los eventos más interesantes (como los eventos de clic) se publican y no se envían y, por lo tanto, pueden supervisarse con este filtro

Cuestiones relacionadas