Il modo migliore per sospendere gli eventi di controllo in Windows Form?
Domanda
Sembra un problema molto semplice e molto comune. L'esempio più semplice che mi viene in mente è questo:
Il modulo ha cinque caselle di controllo con " controlla tutto / controlla nessuno " casella di controllo sopra di loro. Quando un utente seleziona il controllo di tutte le caselle di controllo, seleziono gli stati dei "figli" - ovviamente non voglio attivare gli eventi di controllo di tutti i bambini fino a quando non avrò impostato tutte le caselle di controllo.
Non riesco a trovare un evento di controllo della sospensione a livello di modulo. Se semplicemente mi manca, allora un'ottima risposta semplice. Escludendo una soluzione semplice che mi manca, qual è il modo migliore (best practice? Soluzione accettata?) Per sospendere gli eventi di controllo dei moduli?
Soluzione
L'ho già visto prima e di solito ho visto persone fare questo:
/*SNIP*/
private bool isMassUpdate;
public void Check1_Check(object sender, EventArgs e)
{
if(!isMassUpdate)
{
do some stuff
}
}
/*SNIP*/
Puoi anche staccare e ricollegare i gestori di eventi, tuttavia, mi è stato detto che può essere una fonte di perdite di memoria.
Informazioni sulle perdite di memoria e sui gestori di eventi: non sono direttamente collegati all'aggancio e al distacco, ma in una delle nostre applicazioni abbiamo visto che un cattivo riferimento a gestori di eventi in alberi di ereditarietà può causarlo.
Altri suggerimenti
Quello che faccio in questi casi invece di avere un valore booleano che sospende gli eventi, uso un contatore. Quando il conteggio è > 0, quindi sospendi gli eventi, quando count = 0, quindi riprendi gli eventi. Questo aiuta con il problema se ho più cose che potrebbero richiedere una sospensione degli eventi.
L'altra cosa utile è se ho bisogno di sospendere gli eventi in un blocco, creo una piccola classe di supporto che è IDisposable che posso usare in un " usando " blocco (in C #), quindi non dimentico di decrementare il contatore una volta che sono fuori portata.
Dall'altra tua domanda, ho intenzione di indovinare che stai usando VB .NET. Quindi, RemoveHandler è la soluzione migliore. Normalmente in VB le persone configurano i gestori di eventi usando la clausola Handles. Ma puoi anche farlo in questo modo:
AddHandler chk1.CheckedChanged, AddressOf DoSomething
dove DoSomething potrebbe apparire così:
Private Sub DoSomething(ByVal sender As Object, ByVal e As EventArgs)
' whatever
End Sub
AddHandler collega l'evento, quindi verrà generato. Per evitare che si attivi, usa RemoveHandler:
RemoveHandler chk1.CheckedChanged, AddressOf DoSomething
Prima di aggiornare le caselle di controllo Proprietà controllata di tuo figlio, chiama RemoveHandler su ognuna di esse; quindi, al termine, chiamare AddHandler per ripristinare i gestori di eventi. Se tutte le caselle di controllo utilizzano lo stesso gestore, puoi inserirle in una raccolta e scorrere la raccolta per aggiungere o rimuovere i gestori.
Puoi anche considerare la gestione di eventi "click" per i pulsanti, piuttosto che il check-change. Potrebbe essere più vicino al tuo intento.
Nella mia Visual Basic 6.0 ho dovuto gestire gli utenti facendo doppio clic < em> tutto , quindi su tutti i gestori di eventi ho una riga che controlla una variabile globale
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
Vedi la domanda di overflow dello stack Come posso ignorare i semplici eventi che si attivano quando si cambiano gli stati di controllo in Windows Forms in C #?
Nel caso più generale, se si hanno relazioni complesse tra i controlli, è possibile verificare quale controllo ha generato l'evento controllando la propria proprietà Focused ... ogni oggetto dipende solo da se stesso.