¿La mejor manera de suspender eventos de control en Windows Forms?
Pregunta
Esto parece un problema muy simple y muy común. El ejemplo más simple que se me ocurre es este:
El formulario tiene cinco casillas de verificación con un " check all / check none " casilla de verificación encima de ellos. Cuando un usuario selecciona marcar todas las casillas de verificación, alterno los estados de los "niños" - obviamente, no quiero activar los eventos de verificación de todos los niños hasta que termine de configurar todas las casillas de verificación.
No puedo encontrar un evento de control de suspensión en todo el formulario. Si simplemente me lo estoy perdiendo, entonces una gran respuesta simple. Salvo una solución simple que me falta, ¿cuál es la mejor manera (¿mejor práctica? ¿Solución aceptada?) Para suspender los eventos de control de formulario?
Solución
Me he encontrado con esto antes y generalmente he visto a personas hacer esto:
/*SNIP*/
private bool isMassUpdate;
public void Check1_Check(object sender, EventArgs e)
{
if(!isMassUpdate)
{
do some stuff
}
}
/*SNIP*/
También puede separar y volver a conectar los controladores de eventos, sin embargo, me dijeron que esto puede ser una fuente de pérdidas de memoria.
Información sobre pérdidas de memoria y controladores de eventos: no están directamente vinculados a la conexión y desconexión, pero hemos visto en una de nuestras aplicaciones que las malas referencias de los controladores de eventos en los árboles de herencia pueden causarlo.
Otros consejos
Lo que hago en estos casos en lugar de tener un valor booleano que suspende los eventos, uso un contador. Cuando el recuento es > 0, luego suspender eventos, cuando el recuento = 0, luego reanudar eventos. Esto ayuda con el problema si tengo varias cosas que podrían solicitar una suspensión de eventos.
La otra cosa útil es que si necesito suspender eventos en un bloque, creo una pequeña clase auxiliar que es IDisposable que puedo usar en un " utilizando " bloque (en C #) para que no me olvide de disminuir el contador una vez que esté fuera de alcance.
De su otra pregunta, supongo que está utilizando VB .NET. Entonces, RemoveHandler es tu mejor apuesta. Normalmente en VB las personas configuran controladores de eventos utilizando la cláusula Handles. Pero también puedes hacerlo de esta manera:
AddHandler chk1.CheckedChanged, AddressOf DoSomething
donde DoSomething podría verse así:
Private Sub DoSomething(ByVal sender As Object, ByVal e As EventArgs)
' whatever
End Sub
AddHandler conecta el evento, por lo que se disparará. Para que no se dispare, use RemoveHandler:
RemoveHandler chk1.CheckedChanged, AddressOf DoSomething
Antes de actualizar la propiedad marcada de las casillas de verificación de su hijo, llame a RemoveHandler en cada una de ellas; luego, cuando haya terminado, llame a AddHandler para volver a colocar los controladores de eventos. Si todas sus casillas de verificación usan el mismo controlador, puede ponerlas en una colección y recorrer la colección para agregar o eliminar los controladores.
También podría considerar manejar eventos de 'clic' para los botones, en lugar de marcar como cambiado. Eso podría estar más cerca de tu intención.
En mi Visual Basic 6.0 tuve que manejar a los usuarios haciendo doble clic < em> todo , así que en todos mis controladores de eventos tengo una línea que verifica una variable global
Private bSuspendEvents as Boolean
Private Sub Button1_Click()
On Error Goto ErrorHandler
If bSuspendEvents then Exit Sub
bSuspendEvents = True
'Do stuff
NormalExit:
bSuspendEvents = False
Exit Sub
ErrorHandler:
'Handle Error
Resume NormalExit
End Sub
Consulte la pregunta sobre desbordamiento de pila ¿Cómo ignoro los eventos simples que se activan al cambiar los estados de control en C # Windows Forms?
Para el caso más general, si tiene relaciones complejas entre los controles, puede verificar qué control activó el evento al verificar su propia propiedad Focused ... cada objeto solo depende de sí mismo.