Istruzioni per l'uso degli eventi

Le istruzioni per l'uso degli eventi sono definite dalle regole riportate di seguito.

  • Scegliere un nome per l'evento in base alle convenzioni di denominazione per gli eventi consigliate.

  • Quando si fa riferimento agli eventi nella documentazione, utilizzare la frase "an event was raised", anziché "an event was fired" o "an event was triggered".

  • Nei linguaggi che supportano la parola chiave void utilizzare un tipo restituito void per i gestori eventi come mostrato nel seguente esempio di codice C#:

    public delegate void MouseEventHandler(object sender, MouseEventArgs e);
    
  • Quando un evento fornisce dati significativi, quali le coordinate di un clic del mouse, utilizzare classi di dati evento tipizzate in modo sicuro.

  • Le classi di eventi devono estendere la classe System.EventArgs come mostrato nell'esempio riportato di seguito.

    Public Class MouseEventArgs
       Inherits EventArgs 
       ' Code for the class goes here.
    End Class
    [C#]
    public class MouseEvent: EventArgs {}
    
  • Utilizzare un metodo virtuale protected (Protected in Visual Basic) per generare ciascun evento. Questa tecnica non è adatta alle classi sealed, in quanto da esse non possono derivare le classi. Lo scopo del metodo è quello di fornire una modalità che consenta a una classe derivata di gestire l'evento utilizzando un override. Si tratta di una procedura più comune rispetto all'uso di delegati quando lo sviluppatore sta creando una classe derivata. Il nome del metodo assume il formato OnEventName, in cui EventName è il nome dell'evento generato. Esempio:

    Public Class Button
       Private onClickHandler As ButtonClickHandler  
       Protected Overridable Sub OnClick(e As ClickEventArgs)
          ' Call the delegate if non-null.
          If Not (onClickHandler Is Nothing) Then
             onClickHandler(Me, e)
          End If 
       End Sub
    End Class
    
    [C#]
    public class Button 
    {
       ButtonClickHandler onClickHandler;
    
       protected virtual void OnClick(ClickEventArgs e) 
       {
          // Call the delegate if non-null.
          if (onClickHandler != null)
                onClickHandler(this, e);      
       }
    }
    

    La classe derivata può scegliere di non chiamare la classe base durante l'elaborazione di OnEventName. Per tale ragione non includere nel metodo OnEventName qualsiasi elaborazione che sia necessaria al corretto funzionamento della classe base.

  • È necessario presumere che un gestore eventi possa contenere codice. Le classi devono essere pronte a far eseguire quasi tutte le operazioni al gestore eventi e, in tutti i casi, l'oggetto deve essere lasciato in uno stato appropriato dopo l'attivazione dell'evento. Provare a utilizzare un blocco try/finally nel punto del codice in cui è stato attivato l'evento. Poiché lo sviluppatore può eseguire una funzione di callback sull'oggetto per effettuare altre azioni, non si possono fare assunzioni sullo stato dell'oggetto quando il controllo ritorna nel punto in cui è stato attivato l'evento. Esempio:

    Public Class Button
       Private onClickHandler As ButtonClickHandler
       Protected Sub DoClick()
          ' Paint button in indented state.      
          PaintDown()
          Try
             ' Call event handler.
             OnClick()      
          Finally
             ' Window might be deleted in event handler.
             If Not (windowHandle Is Nothing) Then
                ' Paint button in normal state.
                PaintUp()
             End If 
          End Try
       End Sub
       Protected Overridable Sub OnClick(e As ClickEvent)
          If Not (onClickHandler Is Nothing) Then
             onClickHandler(Me, e)
          End If
       End Sub
    End Class
    [C#]
    public class Button
    {
       ButtonClickHandler onClickHandler;
    
       protected void DoClick()
       {
          // Paint button in indented state.
          PaintDown();
             try
          {
             // Call event handler.
             OnClick();         
          }
          finally
          {
             // Window might be deleted in event handler.
             if (windowHandle != null)
                // Paint button in normal state.
                PaintUp();            
          }
       }
    
       protected virtual void OnClick(ClickEvent e)
       {
          if (onClickHandler != null)
             onClickHandler(this, e);
       }
    }
    
  • Utilizzare o estendere la classe System.ComponentModel.CancelEventArgs per consentire allo sviluppatore di controllare gli eventi di un oggetto. Il controllo TreeView, ad esempio, genera un evento BeforeLabelEdit quando l'utente sta per modificare l'etichetta di un nodo. Nell'esempio di codice seguente viene illustrato come l'evento può essere utilizzato da uno sviluppatore per impedire la modifica di un nodo.

    Public Class Form1
       Inherits Form
       Private treeView1 As New TreeView() 
    
       Sub treeView1_BeforeLabelEdit(source As Object, e As NodeLabelEditEventArgs)
          e.CancelEdit = True
       End Sub
    End Class
    [C#]
    public class Form1: Form 
    {
       TreeView treeView1 = new TreeView();
    
       void treeView1_BeforeLabelEdit(object source, 
          NodeLabelEditEventArgs e) 
       {
          e.CancelEdit = true;
       }
    }
    

    Si noti che, in questo caso, non viene generato alcun errore all'utente. L'etichetta è di sola lettura.

    Gli eventi di annullamento non sono appropriati nei casi in cui lo sviluppatore intende annullare l'operazione e restituire un'eccezione. In questi casi, per eseguire l'annullamento è opportuno generare un'eccezione all'interno del gestore eventi, ad esempio è possibile scrivere una logica di convalida in un controllo di modifica come indicato di seguito.

    Public Class Form1
       Inherits Form
       Private edit1 As EditBox = New EditBox() 
    
       Sub TextChanging(source As Object, e As EventArgs)
          Throw New RuntimeException("Invalid edit")
       End Sub
    End Class
    [C#]
    public class Form1: Form 
    {
       EditBox edit1 = new EditBox();
    
       void TextChanging(object source, EventArgs e) 
       {
          throw new RuntimeException("Invalid edit");
       }
    

Vedere anche

Istruzioni di progettazione per gli sviluppatori di librerie di classi | Convenzioni di denominazione per gli eventi | Istruzioni per l'uso dei membri di classe