Defining an Event

If you are not familiar with the delegate model for events, see Handling and Raising Events.

Event functionality is provided by the following elements.

  • A class that holds the event data (for example, EventArgs, ImageClickEventArgs).

  • An event delegate (for example, EventHandler, ImageClickEventHandler).

    Note   The preceding two classes are generally defined outside your control. The following two members are defined in your control.

  • An event member defined in your control. This is identified by the event keyword.

  • A method in your control that invokes the delegates (for example, OnClick, OnTextChanged).

The following sample defines a Click event in the custom control MyButton.

// If the event does not generate data, you do not have
// to define a class for the event data or define an event delegate. 
// Use System.EventArgs for event data
// and System.EventHandler as the event delegate.
// MyButton uses EventHandler and EventArgs.

using System;
using System.Web.UI;

namespace CustomControls 
{  
   public class MyButton: Control, IPostBackEventHandler 
   {     
      // Defines the Click event.
      public event EventHandler Click;

      // OnClick dispatches the event to delegates that
      // are registered with the Click event.
      // Controls that derive from MyButton can handle the
      // Click event by overriding OnClick
      // instead of attaching a delegate. The event data
      // is passed as an argument to this method.
      protected virtual void OnClick(EventArgs e) 
      {     
         if (Click != null) 
         {
            Click(this, e);
         }  
      }
      
      // Method of IPostBackEventHandler that raises change events.
      public void RaisePostBackEvent(string eventArgument)
      {     
         OnClick(EventArgs.Empty);
      }
      
      protected override void Render(HtmlTextWriter output) 
      {     
         output.Write("<INPUT TYPE = submit name = " + this.UniqueID + 
            " Value = 'Click Me' />"); 
      }
   }    
}
[Visual Basic]
' If the event does not generate data, you do not have
' to define a class for the event data or define an event delegate. 
' Use System.EventArgs for event data
' and System.EventHandler as the event delegate.
' MyButton uses EventHandler and EventArgs.
Option Explicit
Option Strict

Imports System
Imports System.Web.UI

Namespace CustomControls
   Public Class MyButton
      Inherits Control
      Implements IPostBackEventHandler
      
      ' Defines the Click event.
      Public Event Click As EventHandler
      
      ' OnClick dispatches the event to delegates that
      ' are registered with the Click event.
      ' Controls that derive from MyButton can handle the
      ' Click event by overriding OnClick
      ' instead of attaching a delegate. The event data
      ' is passed as an argument to this method.
      Protected Overridable Sub OnClick(e As EventArgs)
         RaiseEvent Click(Me, e)
      End Sub
      
      ' Method of IPostBackEventHandler that raises change events.
      Public Sub RaisePostBackEvent(eventArgument As String) Implements IPostBackEventHandler.RaisePostBackEvent
         OnClick(EventArgs.Empty)
      End Sub 'RaisePostBackEvent
      
      Protected Overrides Sub Render(output As HtmlTextWriter)
         output.Write(("<INPUT TYPE = submit name = " & Me.UniqueID & " Value = 'Click Me' />"))
      End Sub
   End Class
End Namespace

In addition to defining an event, a control developer must also decide how to raise the event (from where to invoke the OnEventName method). For example, MyButton raises the Click event from its RaisePostBackEvent method (which is part of the IPostBackEventHandler contract). For more details about this sample, see Capturing Postback Events.

Optimizing Event Implementation

The event implementation described above is not optimized for performance. It generates one field per delegate instance, which increases storage cost when many events are defined on a control. The base class System.Web.UI.Control provides a more efficient data structure (through its Events property) for storing and retrieving event delegates. The Events property is of type EventHandlerList, which is a data structure that is designed for efficient storage and retrieval of event delegates. The following sample demonstrates event implementation using the Events property. This C# sample differs from the MyButton sample defined earlier in this topic only in its implementation of the Click event. The code that implements this event is highlighted in boldface font.

Note   Event properties are not supported in Visual Basic .NET in this release.

using System;
using System.Web.UI;

namespace CustomControls 
{
   public class OptimizedEventButton: Control, IPostBackEventHandler 
   {
      // Defines a key for storing the delegate for the Click event
      // in the Events list.
      private static readonly object ClickEvent = new object();
      
      // Defines the Click event using the event property syntax.
      // The Events property stores all the event delegates of
      // a control as name/value pairs. 
      public event EventHandler Click 
      {
         // When a user attaches an event handler to the Click event 
         // (Click += myHandler;), the Add method 
         // adds the handler to the 
         // delegate for the Click event (keyed by ClickEvent 
         // in the Events list).
         add          {            Events.AddHandler(ClickEvent, value);         }
         // When a user removes an event handler from the Click event 
         // (Click -= myHandler;), the Remove method 
         // removes the handler from the 
         // delegate for the Click event (keyed by ClickEvent 
         // in the Events list).
         remove          {            Events.RemoveHandler(ClickEvent, value);         }
      }
      
      // Invokes delegates registered with the Click event.
      //
      protected virtual void OnClick(EventArgs e) 
      {
         // Retrieves the event delegate for the Click event
         // from the Events property (which stores
         // the control's event delegates). You must
         // cast the retrieved delegate to the type of your 
         // event delegate.
         EventHandler clickEventDelegate = (EventHandler)Events[ClickEvent];         if (clickEventDelegate != null) {            clickEventDelegate(this, e);         }  
      }
      
      // Method of IPostBackEventHandler that raises change events.
      //
      public void RaisePostBackEvent(string eventArgument)
      {
         
         OnClick(new EventArgs());
      }
      
      protected override void Render(HtmlTextWriter output) 
      {
         
         output.Write("<INPUT TYPE = submit name = " + this.UniqueID + 
            " Value = 'Click Me' />"); 
      }
   }    
}

Note   For simplicity, some of the other samples in the documentation define events using event fields. In your controls, however, you should use the optimized implementation discussed here.

See Also

Handling and Raising Events | Bubbling an Event | Processing Postback Data | Capturing Postback Events | Generating Client-Side Script for Postback