Event handler patterns.
Adding an event to a control is simple. The easiest case is if you can reuse an existing EventArgs class (and therefore also its delegate declaration). e.g.
class MyControl : … {
public event EventHandler MyEvent;
protected virtual void OnMyEvent(EventArgs e) { if (MyEvent != null) MyEvent(this, e); }
}
Raise the event at one or more places in MyControl’s code by calling:
OnMyEvent(new EventArgs());
Declare a event handler for the event in client code:
void MyClientEventHandler(object sender, EventArgs e) { …do stuff to “handle” the event… }
Attach the event handler to the event from client code by:
myControlObject.MyEvent += new EventHandler(this.MyClientEventHandler);
Observations:
1. The “event” keyword causes the compiler to declare a private member of the given type (which must be a delegate type) and += and -= operators for registering and unregistering methods with the delegate.
2. An event is raised (a delegate is invoked) by using the event (delegate) name as a method name.
3. The pattern of declaring a virtual OnEvent method makes it easy to raise the event and allows derived classes full control around event raising.
4. There are two patterns for events: event fields and event properties. The method described above is the event field method and is less storage efficient (each event has its own object for managing attached delegates) than the event property method (example below) which allows for shared storage of event delegates. The EventHandlerList class is used by the Component class Events property.
public class OptimizedEventButton: Control { // 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 component 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); } }
Instead of EventArgs, a class derived from EventArgs can be used. In this case a new delegate type must be defined that uses the new event arg class.
For MyEventArgs, the delegate would be:
public delegate void MyEventHandler(object sender, MyEventArgs e);
2002-07-23 18:22 Tue, dotNET, Event Handler pattern in custom controls