2010-09-24 15 views
7

Quando ho utilizzare AddHandler in VB per aggiungere il mio proprio metodo per l'evento Click:Aggiunta proprio gestore di eventi di fronte ad altri gestori di eventi

AddHandler Button.Click, AddressOf myButton_Click 

vedo che il mio codice esegue l'ultima - dopo che altri gestori di eventi per la Evento Button_Click. C'è un modo per inserire il mio gestore di eventi davanti di altri eventi in modo che esso esegue prima?

ho tagged questa domanda come C# e VB, non esitare a utilizzare eitherlanguage se avete suggerimenti.
Grazie!

risposta

5

L'ordine di esecuzione dei gestori di un singolo evento non può essere controllato attraverso il comportamento di base di un built-in dell'evento stesso. MulticastDelegates sono "borse" di gestori e li afferrano solo uno alla volta. Tieni presente che questo è il modo in cui la maggior parte degli sviluppatori si aspetta che funzioni, e può essere pericoloso consentire ai gestori di eventi dipendenti dall'ordine. I gestori di eventi dovrebbero normalmente non conoscersi l'un l'altro, perché se dipendono dall'essere eseguiti prima o dopo un altro gestore, devono prima conoscere l'esistenza dell'altro gestore (violando il nascondiglio delle informazioni e molti altri principi di progettazione), e secondo, se quell'ordine cambia, il comportamento sarà interrotto.

Se si capisce tutto questo, e ancora voglia di controllare l'ordine di esecuzione dei gestori di un evento, di seguito si arriva vicino.

  1. Creare una raccolta ordinata di delegati del tipo di gestore eventi denominata MyHandlers. Questo sarà un surrogato dell'implementazione MulticastDelegate dell'effettivo.
  2. Creare un metodo di gestione "master" che verrà effettivamente associato all'evento incorporato e itererà tramite MyHandlers e chiamerà ciascuno di essi.
  3. Definire alcuni metodi per aggiungere e rimuovere gestori dall'elenco. Alcuni di questi possono essere realizzati con un evento personalizzato "proprietà", ma che definirà solo aggiungere e rimuovere comportamenti, non inserire.

Il codice potrebbe essere simile alla seguente:

private List<EventHandler> MyHandlers = new List<EventHandler>(); 

private void MasterClickHandler(object sender, EventArgs e) 
{ 
    foreach(var handler in MyHandlers) 
     handler(sender, e); 
} 

public event EventHandler MyControlButtonClick 
{ 
    add { MyHandlers.Add(value); } 
    remove { MyHandlers.Remove(value); } 
} 

public void InsertButtonClickHandler(EventHandler handler) 
{ 
    MyHandlers.Insert(handler,0); //calling this to add a handler puts the handler up front 
} 

... 

myForm.MyControl.Click += MasterClickHandler; 

Si noti che non sei più il fissaggio gestori diversi MasterClickHandler per l'evento vero e proprio; non puoi avere la tua torta e mangiarla, sia ignorando che mantenendo il comportamento di base dell'evento.Inoltre, non c'è un comportamento di "inserimento" incorporato nell'evento "proprietà"; devi definire un metodo che permetta questo. Infine, non devi mai aumentare l'evento MyControlButtonClick direttamente (anche se il tuo controllo è l'unico che può, questo può essere applicato mediante l'ispezione del codice).

Ora, quando si fa clic sul pulsante, l'evento Click incorporato del pulsante fa scattare MasterEventHandler, che eseguirà i delegati in MyHandlers nello stesso ordine in cui sono stati collegati a MyControlButtonClick (con quelli inseriti prima per primi, nel retro ordine in cui sono stati inseriti). Se hai inserito questo codice in un controllo utente personalizzato con il pulsante, potresti anche nominare l'evento personalizzato sul tuo controllo Fai clic e il controllo apparirebbe e funzionerà in modo molto simile al pulsante in esso contenuto, tranne che avrebbe il controllo extra sull'inserimento gestori. La bellezza dell'intera cosa è che nulla su questo codice costringe i consumatori a lavorare con esso come qualcosa di diverso da un semplice evento di vaniglia.

11

Non facilmente.

Detto questo, non farlo. Il tuo codice non dovrebbe preoccuparsi di quale ordine è chiamato - dovrebbe solo preoccuparsi che il pulsante in questione sia stato cliccato. Verranno eseguiti tutti i gestori, incluso il tuo. Se l'ordine è importante, è necessario riconsiderare il design e utilizzare un altro meccanismo per controllarlo.

+0

+1 per il buon consiglio. –

4

È più di un dettaglio di implementazione di VB.NET, è un modo alternativo di trattare con gli eventi utilizzando i WithEvents e Handles parole chiave. Un gestore di eventi che utilizza Handles viene sottoscritto da un codice generato automaticamente nel costruttore di moduli. Questo codice verrà eseguito prima di qualsiasi codice, incluso InitializeComponent o l'istruzione AddHandler personalizzata. E quindi funzionerà sempre per primo.

Ottenere il codice per garantire di eseguire prima è possibile. Derivare la propria classe da Button e l'override del metodo OnClick:

Public Class MyButton 
    Inherits Button 

    Protected Overrides Sub OnClick(ByVal e As System.EventArgs) 
     '' Do your stuff here 
     ''.... 

     '' Other event handlers will run now: 
     MyBase.OnClick(e) 
    End Sub 
End Class 
2

Ho avuto un problema simile.

Ho avuto un evento: Chiuso che due oggetti diversi ascoltano. E dovevo essere sicuro che l'evento del primo oggetto sarà chiamato prima del 2 °.

Qui la sua la mia soluzione (in C#):

public class Screen 
{ 
    public event EventHandler Closed; 
    public event EventHandler ScreenRemoved; 


    protected virtual void OnClosed() 
    { 
     if (Closed != null) 
     { 
      Closed.Invoke(this, EventArgs.Empty); 
     } 

     OnScreenRemoved(); 
    } 

    protected virtual void OnScreenRemoved() 
    { 
     if (ScreenRemoved != null) 
     { 
      ScreenRemoved.Invoke(this, EventArgs.Empty); 
     } 
    } 
} 

In questo modo per tutti gli eventi che voglio essere chiamato prima:

m_Screen.Closed += Screen_Closed; 

E per tutti gli eventi che voglio essere chiamato ultima:

m_Screen.ScreenRemoved += new EventHandler(Screen_Closed); 

* sia modo l'aggiunta di un evento sono gli stessi, con e senza "new EventHandler()"

Spero di essere stato utile.

Problemi correlati