Beginning With Events
Before we start, I just want to say that I think understanding how to create and consume events is extremely important as a developer. I was surprised that none of the developers (including the development director) knew how to create events and how useful they can be.
As developers, we're use to consuming events on a daily basis. For example, one of the most common events we consume is 'Page.Load'. Other ones we use for a page include 'Init' and 'PreRender'. Then of course are the control events such as 'Button.Click' and 'DropDownList.SelectedIndexChanged'.
So consuming event's is pretty easy. The button control has a click event that can be hooked up as follows:
myButton.Click += new EventHandler(myButton_Click);
And of course, there is a method called 'myButton_Click' that gets 'fired' when the event occurs. You can think of the 'myButton_Click' method as 'subscribing' to the event. And with all subscription models, more than 1 method can subscribe to an event. So the following code is perfectly valid:
myButton.Click += new EventHandler(myButton_Click);
myButton.Click += new EventHandler(anotherMethod_Click);
Naturally both methods must exist, otherwise you get a compile error. You can also programatically UNSUBSCRIBE a method from an event with the syntax:
myButton.Click -= new EventHandler(myButton_Click);
So lets look a little closer at this code. What does the 'EventHandler' part mean?
Well take a look at the 'myButton_Click' method. Here is its signature:
void myButton_Click(object sender, EventArgs e)
If we were to change this signature in any way (other than the parameter names) we would get a compile error. This is because the 'EventHandler' defines this signature, and therefore any method that subscribes via that declaration must implement the exact signature. Under the hood, when the button raises the Click event, it is sending information such as the sender and the event arguments. If you are subscribing to that event, then you must also receive that information. Therefore, the EventHandler states the rules of what the event will raise and what the subscribing method will handle.
Here's another example. In ASP.Net there is a control called 'GridView', and one of its events is 'PageIndexChanging'. To handle that event, code might look like this:
myGrid.PageIndexChanging += new GridViewPageEventHandler(myGrid_PageIndexChanging);
As you can see, the 'contract' for the subscription is called 'GridViewPageEventHandler'. When implemented, this ensures the method handles some different arguments. Its the event that defines what event handler to use for its signature, and all subscribing methods must implement that signature. When writing events, you can use these existing handlers, or you can create your own. More on this later.
Now we understand more about consuming events, lets create one. Imagine an object called 'TrafficLight' which simply rotates between the colours as a normal traffic light would. Internally it has a timer that after X number of seconds changes the colour. When the traffic light changes colour, it should 'raise an event' so that the rest of the application is aware that the change has occurred; perhaps we have a visual control that would show the traffic light and it wants to subscribe to the traffic light's colour changing event.
So creating the event is very easy. We will use an existing event handler:
public event EventHandler LightChanged;
This declaration states that there will be an event called 'LightChanged' and that it will use the method signature as defined by 'EventHandler'. Naturally there's not much point making the event private because nothing outside of the class could subscribe to it!
In the code, we would be raising the event when the timer ticks (Timer.Elapse) because that's when the light colour changes. Our code might look like this:
if (LightChanged != null) LightChanged(this, new EventArgs());
First lets look at the IF statement. This is a simple safety check that says not to raise the event unless something has subscribed to it. If no one is subscribing to an event and that event gets raised, a runtime exception will occur. So we check that its not null first. Then we simply call 'LightChanged' as if it was a method. And guess what? It IS a method! In fact, its the method that subscribed to the event. LightChanged is just a placeholder for functionality that might be added later.
Ok so the last thing we need to think about is that the information we are raising in the event is not very useful to the subscriber. We should actually include more helpful stuff, like the new light colour. So this is where we can define our own event handler:
public delegate void LightChangedEventHandler(TrafficLight sender, ColourStatus NewColour);
As we know from previous usage, the LightChangedEventHandler just defines a signature that the event and subscribers adhere to. In a way its similar to the contracts defined in interfaces. The keyword 'delegate' is special here because it says that this method signature is like a 'type'. The actual event instantiates that type.
So we now need to change the declaration of the event:
public event LightChangedEventHandler LightChanged;
And change how the event gets raised:
if (LightChanged != null) LightChanged(this, CurrentLightColour);
Well that's it. Best to have a play. I've completed the TrafficLight solution for you to see how it all comes together (VS2006 / .Net 2.0). I apologise in advance for using the Traffic Light example. I know its been done to death but it really is an excellent example of events. Feel free to post any questions/comments here as usual.
Labels: C#, EventHandler, events, TrafficLight, VS2005
0 Comments:
Post a Comment
<< Home