KnowDotNet NetRefactor

Creating and Handling Events - Part 2

by Brian Davis
Print this Article Discuss in Forums

In Part 1 of this tutorial, we learned how to create simple events that did not require any additional data to be passed along with the event.  Often, however, we need to convey some information about the event, so these simple events are not sufficient.  Consider the MouseDown event of a Windows Forms TextBox control.  In order to convey which mouse button was clicked, where the location of the pointer is, etc., Microsoft uses a class called MouseEventArgs instead of just EventArgs.  You can do the same thing with your events, and it doesn't require much additional code.

In Part 1, we were using a
Car class as an example.  We had the simple event Started.  Now we will add a more complex event - CruiseControlSet.  When a driver sets the cruise control on a car, the car will maintain its current speed until the driver breaks or cancels the cruise control.  With this event, we want to not only notify other classes that the cruise control was set, we also want to let them know what speed it has been set to maintain.  To do this, we need our own special derivitive of the EventArgs class.  We create a class called CruiseControlSetEventArgs that inherits from EventArgs.

VB
Public Class CruiseControlSetEventArgs
  
Inherits EventArgs

  
Public CruiseControlSpeed As Integer

  Public Sub New(ByVal speed As Integer)
      
Me.CruiseControlSpeed = speed
  
End Sub

End
Class


C#
public class CruiseControlSetEventArgs : EventArgs
{
  
public int CruiseControlSpeed;

  
public CruiseControlSetEventArgs(int speed)
   {
      
this.CruiseControlSpeed = speed;
   }
}


Once we have a class to hold our extra data, we need a new delegate to serve as a special event handler for our event.  This delegate will make sure that other classes handle our event properly, receiving both the sender and our special event args.

VB
Public Delegate Sub CruiseControlSetEventHandler(ByVal sender As Object, ByVal e As CruiseControlSetEventArgs)

C#
public delegate void CruiseControlSetEventHandler(object sender, CruiseControlSetEventArgs e);


Now we are ready to create our event.  This is done like our simple event, but we make sure that our special event handler is used instead of the default
EventHandler delegate.

VB
Public Event CruiseControlSet As CruiseControlSetEventHandler

C#
public event CruiseControlSetEventHandler CruiseControlSet;


Raising our customized event is also nearly identical to raising the simple event from before.  For C#, we create our special On
Event method and raise the event by calling the method.

C#
protected virtual void OnCruiseControlSet(CruiseControlSetEventArgs e)
{
  
if(this.CruiseControlSet != null)
   {
      
this.CruiseControlSet(this, e);
   }
}
...
this.OnCruiseControlSet(new CruiseControlSetEventArgs(speed));

To raise the event in VB, we again use the RaiseEvent keyword, indicating the event that should be raised and passing a default instance of our custom EventArgs.

VB
' The speed that has been set is stored in a variable named "speed"
RaiseEvent CruiseControlSet(Me, New CruiseControlSetEventArgs(speed))


Putting all of this together with the code from Part 1, here is what our new code would look like:

VB
Public Class CruiseControlSetEventArgs
  
Inherits EventArgs

  
Public CruiseControlSpeed As Integer

  Public Sub New(ByVal speed As Integer)
      
Me.CruiseControlSpeed = speed
  
End Sub

End
Class

Public
Delegate Sub CruiseControlSetEventHandler(ByVal sender As Object, ByVal e As CruiseControlSetEventArgs)

Public Class Car

  
Public Event Start As EventHandler
  
Public Event CruiseControlSet As CruiseControlSetEventHandler

  
Public Sub StartEngine()
      
' *** CODE TO START CAR ***

     ' Raise event to notify others
     RaiseEvent Start(Me, New EventArgs)
  
End Sub

  Public Sub SetCruiseControl(ByVal speed As Integer)
      
' *** CODE TO SET CRUISE CONTROL ***

     ' Raise event to notify others
     RaiseEvent CruiseControlSet(Me, New CruiseControlSetEventArgs(speed))
  
End Sub

End
Class

C#
public class CruiseControlSetEventArgs : EventArgs
{
  
public int CruiseControlSpeed;

  
public CruiseControlSetEventArgs(int speed)
   {
      
this.CruiseControlSpeed = speed;
   }
}

public delegate void CruiseControlSetEventHandler(object sender, CruiseControlSetEventArgs e);

public class Car
{
  
public event EventHandler Start;
  
public event CruiseControlSetEventHandler CruiseControlSet;

  
protected virtual void OnStart(EventArgs e)
   {
      
if(this.Start != null)
      {
        
this.Start(this, e);
      }
   }

  
protected virtual void OnCruiseControlSet(CruiseControlSetEventArgs e)
   {
      
if(this.CruiseControlSet != null)
      {
        
this.CruiseControlSet(this, e);
      }
   }

  
public void StartEngine()
   {
      
// CODE TO START ENGINE

     // Raise event to notify others
     this.OnStart(new EventArgs());
   }

  
public void SetCruiseControl(int speed)
   {
      
// CODE TO SET CRUISE CONTROL

     // Raise event to notify others
     this.OnCruiseControlSet(new CruiseControlSetEventArgs(speed));
   }
}


We now have a
Car class that will notify others when it is started or its cruise control is set.  Additionlly, when the cruise control is set, classes can determine what speed is being maintained by using our custom CruiseControlSetEventArgs class.  In Part 3 of the tutorial, we will learn how to handle these events in another class.


Writing Add-Ins for Visual Studio .NET
Writing Add-ins for Visual Studio .NET
by Les Smith
Apress Publishing