An Event is a message sent out by an object to notify other objects that an action/trigger/state-change (ie. an event) has taken place. Therefore, you should use an event when an object's state change requires other objects to change as well.
The object that sends an event is known as the event sender.
The object that receives (or listens for) the event is known as the event receiver.
Events implement the "Observer Design Pattern". This pattern contains two key objects: a subject (the event sender), and an observer (the event receiver). The subject may have one or many observers.
Delegates are used in order to communicate between the sender and the receiver objects since the sender does not know what object type may be receiving (or handling) the event. The Delegate connects the Event with it's receiver (or handler).
Recall that, in .NET, Delegates are classes that serve as function pointers. They hold a reference (memory location) to a method. Also remember that Delegates can only hold references to methods that match its signature.
The Delegate identifies the method that provides the response to the event and holds the event data.
Using Generic Events (EventHandler Delegate)
A generic event handler delegate has been made available in the.NET Framework 2.0. It's referred to as EventHandler.
The EventHandler delegate holds a reference to a method that handles events raised which do not contain event data. In other words, it represents the method that will handle a typical event.
The EventHandler delegate's signature is as follows:
Expand|Select|Wrap|Line Numbers
- Public Delegate Sub EventHandler(ByVal sender As Object, ByVal e As EventArgs)
Expand|Select|Wrap|Line Numbers
- public delegate void EventHandler(Object sender, EventArgs e)
- The "sender" parameter is the object raising the event.
- The "e" parameter is the event arguments that are passed back to the receiving object and contain data about the event. Since the event doesn't generate event data, this parameter is an instance of EventArgs.
- If you require the event to generate event data (data that can be used by the receiving object in order to process something), then you cannot use the EventHandler. Instead you must use the EventHandler<T>. This is explained in more detail in the next section.
So if you needed to raise an event that does not generate event data you would declare your event as:
Expand|Select|Wrap|Line Numbers
- Public Event NoDataEventHandler As EventHandler
- 'EventHandler is the delegate that holds a reference to a method with the signature: (Object sender, EventArgs e)
- 'You do not need to create a delegate called EventHandler as this is now part of the System class
Expand|Select|Wrap|Line Numbers
- Private Sub OnMyEvent()
- RaiseEvent NoDataEventHandler(Me, New EventArgs())
- End Sub
Using Events That Return Event Data (EventHandler<T> Delegate)
If, when you raise the event, you need to pass data to the receiving objects, you cannot use the EventHandler delegate. Instead you need to use EventHandler<T>.
Since your event generates event data, you must first create a custom type to hold this data. This custom type has to be derived from EventArgs.
Expand|Select|Wrap|Line Numbers
- Public Class MyObjectsEventArgs
- Inherits EventArgs
- Private _theEventData As String
- Public Sub New(ByVal eventData As String)
- _theEventData = eventData
- End Sub
- Public Property Message() As String
- Get
- Return _theEventData
- End Get
- Set(ByVal value As String)
- _theEventData = value
- End Set
- End Property
- End Class
Expand|Select|Wrap|Line Numbers
- Public Delegate Sub XEventHandler(Of MyObjectsEventArgs)(ByVal sender as Object, ByVal e As MyObjectsEventArgs)
- 'Note that MyObjectsEventArgs is the custom type derived from EventArgs used to pass the event data to the receiving class.
Now that you have a delegate to use to link the sender and receiver classes, you can declare an event as:
If you declare you Delegate as:
You will receive a warning from the compiler (run using code analysis):Expand|Select|Wrap|Line Numbers
- Public Delegate Sub XEventHandler(ByVal sender as Object, ByVal e As MyObjectsEventArgs)
- 'Note that MyObjectsEventArgs is the custom type derived from EventArgs used to pass the event data to the receiving class.
... generates EventHandler delegates for events that use the following pattern: Event MyEvent(ByVal Sender As Object, ByVal e As MyEventArgs). Change the event that defines EventHandler 'EventHandler' to use EventHandler<T> ..."It is complaining that you are declaring a Delegate that uses the EventHandler's signature except that you are not using EventArgs in the signature.
Expand|Select|Wrap|Line Numbers
- Public Event SendMessageEvent As XEventHandler(Of MyObjectsEventArgs)
To raise the event in your sender code you would do the following:
Expand|Select|Wrap|Line Numbers
- Private Sub OnMyEvent(ByVal message As String)
- RaiseEvent SendMessageEvent(Me, New MyObjectsEventArgs(message))
- End Sub
Expand|Select|Wrap|Line Numbers
- Private Sub TestEventSending_theEvent(ByVal sender As Object, ByVal e As MyObjectsEventArgs) Handles TestEventSending.SendMessageEvent
- 'Note that "TestEventSending" is the instance of the Sender Object used in my Receiving Object
- Label_Message = e.Message
- 'e is an instance of the MyObjectsEventArgs class we implemented to be able to send event data to the receiving object for it to use
- 'Recall that Message is a property of MyObjectsEventArgs that we defined to hold our event data
- End Sub
EventHandler Generic Delegate
EventHandler(TEventArgs) Generic Delegate