In progrmaming, an
event is how we generally refer to actions that the user takes.
When they open the program, click a button, select an option from a list of radio buttons, or type in their
e-mail address, these are all broadly classified as
events. It will often be upon
ourselves to build the program to respond to many of these events, in either visible ways to the user ("Your
password must contain at least one numeric digit, one astrological sign, and one line of lyrics from 'Never
Gonna Give You Up' by Rick Astley") or in ways hidden from the user ("Daniel's purchased a lot of blu-ray
movies starring Karen Gillian... maybe we'll suggest this one he hasn't bought yet."
Such a movie doesn't
exist, by the way — I own them all!). Handling
events is one of the
most effective ways to create software that dynamically responses to the user, enabling a sense of immersion
with whatever process is taking place. This immersion is vital for keeping users engaged with the software.
There are two "actors" when it comes to
events: the publisher (the class which
broadcasts the occurrence of an event), and one or more subscribers (other class(es) that response to the
event). So for example, a Form may detect a
ButtonClick event, which a
Handler may respond with by incrementing an invisible counter of how many times a
ButtonClick event occurred. Once the counter reaches 42, a pop-up window is spawned,
reminding the user to not forget their towel.
Now, because there can be multiple subscribers, each of whom will want to respond to the broadcast of an
event, you might have guessed that use of a
delegate can
help organize this. Indeed,
events are a special kind of
multicast
delegate that can only be invoked from within the
struct or
class in which they are defined. The subscribers will add their method to the linked list invoked by
this
multicast delegate. By convention, we code these
multicast
delegates with a name ending in "Handler".
There are a lot of moving parts when it comes to correctly implementing a publisher/subscriber relationship
in your program, so you'll want to devote some time to making sure you understand the fundamental mechanics
and syntax. Let's break down one example, from the one I mentioned above referring to Douglas Adams' famous
novel,
The Hitchhiker's Guide to the Galaxy.
public namespace ManyEventsHandleIt
{
public class
FunnyEventArgs : EventArgs // This is how I transmit information about the event
{
public int HowMany { get; set; } // Auto-implemented
public DateTime TimeStamp { get; set; }
}
public class
TowelCounter // This will be my publisher class
{
private readonly int life = 42;
public int total;
public event EventHandler<
FunnyEventArgs>
TheJoke;
public
TowelCounter() : total(0) { }
// This method will broadcast the event to subscribers
protected virtual void
TimeForTheJoke(
FunnyEventArgs argData)
{
EventHandler<
FunnyEventArgs> handler =
TheJoke;
if (handler != null)
{
handler(this, argData); // The first argument will almost always be "this"
}
}
public void step() // This simple mechanism is what will ultimately trigger this event
{
total++;
if (total >= life) // Time to let the people know!
{
FunnyEventArgs args = new FunnyEventArgs();
args.HowMany = (total - life) + 1;
args.TimeStamp = DateTime.Now;
// Finally, we'll call the method that invokes the handler
TimeForTheJoke(args);
}
}
}
public class MyJokeProgram
{
// Here is one of my subscribers
static void Joke
Handler(object sender,
FunnyEventArgs args)
{
if (args.HowMany > 1)
MessageBow.Show("Don't forget to bring your {0} towels!", args.HowMany);
else if (args.HowMany == 1)
MessageBow.Show("Don't forget to bring your towel!");
}
public
TowelCounter towel;
public JokeWindow()
{
towel = new TowelCounter();
// This next line will attach the subscriber to publisher
towel.TheJoke += JokeHandler;
myButton.Click += new EventHandler(this.myButton_ClickEvent);
}
public void myButton_ClickEvent(Object sender, EventArgs args)
{
towel.step();
}
}
}
I color-coded this because the example I was reading from was horrendously disorganized, so this helped me keep
all the bits straight. If it helped you too, that's even better. And sort of the whole point of these class
notes...
It won't take us long to begin implementing various
EventHandlers and indeed, if you
go on to work in this industry, you can expect there to be plenty of iterations of this type of code. So it would
not at all be a waste of your time to closely and carefully study this code, practice its implementation, and
then practice some more. It will do wonders for your productivity if you can bust out most of this code without
having to refer back to MSDN documentation and/or old source code.