Click here to Skip to main content
11,412,578 members (71,990 online)
Click here to Skip to main content

Events and event handling in C#

, 16 Oct 2001 CPOL
Rate this:
Please Sign up or sign in to vote.
An introduction to using events and event handlers in C#

Introduction

An event is a mechanism via which a class can notify its clients when something happens. For example when you click a button, a button-click-event notification is sent to the window hosting the button. Events are declared using delegates. So if you don't know what a delegate is, you may go and read my article on delegates first. The first time you go through this article you might find it confusing, don't worry about that. Just try out the sample program and go through the sample source, line by line. Maybe, you can read the article once more after that. Once you get the hang of it, things will seem simple. By the way this article is intended for beginners and is not meant for advanced level programmers.

The Program

I include the full program below. It's not commented but later down this article, I have taken the program part by part and explained each part. I have also included the output you'll get on running the program.

using System;

public delegate void DivBySevenHandler(object o, DivBySevenEventArgs e);

public class DivBySevenEventArgs : EventArgs
{
    public readonly int TheNumber;
    
    public DivBySevenEventArgs(int num)
    {
        TheNumber = num;
    }    
    
}

public class DivBySevenListener
{
    public void ShowOnScreen(object o, DivBySevenEventArgs e)
    {
        Console.WriteLine(
            "divisible by seven event raised!!! the guilty party is {0}",
            e.TheNumber);
    }    
}

public class BusterBoy
{
    public static event DivBySevenHandler EventSeven;
    
    public static void Main()
    {
        DivBySevenListener dbsl = new DivBySevenListener();
        EventSeven += new DivBySevenHandler(dbsl.ShowOnScreen);
        GenNumbers();
    }
    
    public static void OnEventSeven(DivBySevenEventArgs e)
    {
        if(EventSeven!=null)
            EventSeven(new object(),e);
    }    
    
    public static void GenNumbers()
    {
        for(int i=0;i<99;i++)
        {
            if(i%7==0)
            {
                DivBySevenEventArgs e1 = new DivBySevenEventArgs(i);
                OnEventSeven(e1);
            }
        }        
    }
        
}
//Output

F:\c#\events>1
divisible by seven event raised!!! the guilty party is 0
divisible by seven event raised!!! the guilty party is 7
divisible by seven event raised!!! the guilty party is 14
divisible by seven event raised!!! the guilty party is 21
divisible by seven event raised!!! the guilty party is 28
divisible by seven event raised!!! the guilty party is 35
divisible by seven event raised!!! the guilty party is 42
divisible by seven event raised!!! the guilty party is 49
divisible by seven event raised!!! the guilty party is 56
divisible by seven event raised!!! the guilty party is 63
divisible by seven event raised!!! the guilty party is 70
divisible by seven event raised!!! the guilty party is 77
divisible by seven event raised!!! the guilty party is 84
divisible by seven event raised!!! the guilty party is 91
divisible by seven event raised!!! the guilty party is 98

F:\c#\events>

Explanation

Okay. I presume you have taken a look at the above program and I bet you have all guessed it's purpose. We generate some numbers and every time we generate a number that is divisible by 7 we raise an event. The event handler will print out a message saying that the event was raised and it also prints out the number responsible for raising the event. I guess some of you are frowning and saying that's a stupid reason to raise an event. I know, I know alright. The program is not intended to be used for any useful purpose. It's only an attempt to make events comprehensible. I hope it served it's role out. Smile | :)

Okay, so the first thing we did was to declare a delegate.

public delegate void DivBySevenHandler(object o, DivBySevenEventArgs e);

The delegate defines the parameters sent to the event handlers. Thus any class that wants to handle this event must have a handler method which has the same return type and argument list as this delegate. Here as you can see, the first parameter is an object. In real-world cases event handlers are normally passed a reference to the sending object. I am not doing that in this program. I am simply passing a new object() to the event handler. Normally you can pass a this reference. The second parameter is a System.EventArgs derived class. System.EventArgs is the base class for encapsulating event related data. We use it to send information regarding the event to its handler.

Now, we define the EventArgs derived class as follows:-

public class DivBySevenEventArgs : EventArgs
{
    public readonly int TheNumber;
	
    public DivBySevenEventArgs(int num)
    {
        TheNumber = num;
    }		
}

As you can see, it has a public read-only member which is used to store our generated number that is divisible by 7. Normally you should use properties but for the sake of simplicity I am using a public member variable.

Now we define our listener class which is the class that needs to be notified of the event.

public class DivBySevenListener
{
    public void ShowOnScreen(object o, DivBySevenEventArgs e)
    {
        Console.WriteLine(
            "divisible by seven event raised!!! the guilty party is {0}",
            e.TheNumber);
    }	
}

As you can see, it has a function ShowOnScreen that matches the delegate type we defined on top. You can see how we use the passed DivBySevenEventArgs object to print out the number that is divisible by seven.

Now, let's examine our Main() containing class. We first declare the event as follows:-

public static event DivBySevenHandler EventSeven;

An event is declared like a delegate type variable, except that the keyword event precedes the event declaration.

Now let's take a look at the function that invokes the event and thus notifies all clients.

public static void OnEventSeven(DivBySevenEventArgs e)
{
    if(EventSeven!=null)
        EventSeven(new object(),e);
}

EventSeven will be null if no client has hooked up a delegate to the event. We need to check if it is null unless you want to see an exception raised. If it's not null we invoke the event, passing a dummy object [I have explained above why I passed a dummy] and the passed DivBySevenEventArgs object. And all clients get notified.

Let's look at the function GenNumbers() now :-

public static void GenNumbers()
{
    for (int i=0;i<99;i++)
    {
        if(i%7==0)
        {
            DivBySevenEventArgs e1 = new DivBySevenEventArgs(i);
            OnEventSeven(e1);
        }
    }		
}

We use the for() loop to iterate from 0 to 98, and in each case we check for divisibility by 7. If we find that the number is divisible by 7 we create a DivBySevenEventArgs object passing the culprit number to the constructor. Now we call the OnEventSeven() function passing the DivBySevenEventArgs object we just created. 

Now lets go through Main()

public static void Main()
{
    DivBySevenListener dbsl = new DivBySevenListener();
    EventSeven += new DivBySevenHandler(dbsl.ShowOnScreen);
    GenNumbers();
}

We first create a DivBySevenListener object. Then using the += operator we compose a delegate into the event field. Even though I haven't used the -= operator, you can use it to remove a delegate from an event. Once we've done all that we call GenNumbers(). Thus we've set everything up nice and proper. GenNumbers() will do its job like a faithful puppy by generating numbers from 0 to 98 just as we expected it to. Every time it generates a number divisible by 7 it will raise the event.

Conclusion

Well you have just seen how you can create events and event handlers. You must remember that events can be invoked only from the class that declared them. This causes problems with regard to inheritance. Thus if you have a class with an event you'd better make your OnWhateverEvent() function protected so that the derived classed can call it. Better still, make it virtual too, so they can override it in their class.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Nish Nishant

United States United States
Nish Nishant is a Software Architect/Consultant based out of Columbus, Ohio. He has over 15 years of software industry experience in various roles including Lead Software Architect, Principal Software Engineer, and Product Manager. Nish is a recipient of the annual Microsoft Visual C++ MVP Award since 2002 (13 consecutive awards as of 2014).

Nish is an industry acknowledged expert in the Microsoft technology stack. He authored
C++/CLI in Action for Manning Publications in 2005, and had previously co-authored
Extending MFC Applications with the .NET Framework for Addison Wesley in 2003. In addition, he has over 140 published technology articles on CodeProject.com and another 250+ blog articles on his
WordPress blog. Nish is vastly experienced in team management, mentoring teams, and directing all stages of software development.

Contact Nish : You can reach Nish on his google email id voidnish.

Website and Blog

Comments and Discussions

 
GeneralEvents and event handling in C# Pin
Member 2915055 at 12-Aug-14 3:42
memberMember 291505512-Aug-14 3:42 
GeneralMy vote of 3 Pin
chait301 at 23-Dec-13 2:34
memberchait30123-Dec-13 2:34 
QuestionExcellent article Pin
Dejan Dimeski at 17-Oct-13 10:19
memberDejan Dimeski17-Oct-13 10:19 
GeneralNot quite as simple as I wished for a first example Pin
Timok1A at 5-Aug-13 23:58
memberTimok1A5-Aug-13 23:58 
QuestionThank you Pin
Member 9358205 at 8-Mar-13 11:58
memberMember 93582058-Mar-13 11:58 
Nish,
I got it running in Silverlight with Blend 4. Only had to add a static TextBlock in the class declaration space above MainPage to replace the Console output.

Thanks, I'm indebted.
GeneralMy vote of 5 Pin
naymyohaen at 29-Nov-12 22:37
membernaymyohaen29-Nov-12 22:37 
QuestionWhy not use = instead of += Pin
Member 1482262 at 6-May-12 14:56
memberMember 14822626-May-12 14:56 
AnswerRe: Why not use = instead of += Pin
VuNic at 11-Jun-12 22:10
memberVuNic11-Jun-12 22:10 
AnswerRe: Why not use = instead of += Pin
Shameel at 14-Aug-12 0:50
memberShameel14-Aug-12 0:50 
Questionstatic functions Pin
bjdodo at 5-Mar-12 1:51
memberbjdodo5-Mar-12 1:51 
GeneralMy vote of 4 Pin
Manuel_Perez_II at 7-Aug-11 22:52
memberManuel_Perez_II7-Aug-11 22:52 
GeneralMy vote of 4 Pin
bindum31 at 6-Jul-10 3:23
memberbindum316-Jul-10 3:23 
QuestionCan you talk more clearly about paramenter object and eventargs and more example for them Pin
binhcoolfreestyles at 14-Mar-09 19:24
memberbinhcoolfreestyles14-Mar-09 19:24 
AnswerRe: Can you talk more clearly about paramenter object and eventargs and more example for them Pin
Mark McClure at 26-Apr-09 10:25
memberMark McClure26-Apr-09 10:25 
Generalhandle printer events Pin
chienquang at 13-May-07 23:48
memberchienquang13-May-07 23:48 
GeneralDisable event temporarily Pin
RomanskiSt at 21-Apr-06 2:46
memberRomanskiSt21-Apr-06 2:46 
GeneralRe: Disable event temporarily Pin
yfisaqt at 10-Nov-06 13:14
memberyfisaqt10-Nov-06 13:14 
GeneralRe: Disable event temporarily Pin
Paul French at 17-Apr-07 16:49
memberPaul French17-Apr-07 16:49 
GeneralRe: Disable event temporarily Pin
Member 4745355 at 1-Nov-10 18:02
memberMember 47453551-Nov-10 18:02 
QuestionWould the event be create in a different process? Pin
Albert Pascual at 6-Apr-06 16:49
sitebuilderAlbert Pascual6-Apr-06 16:49 
AnswerRe: Would the event be create in a different process? Pin
James S. Taylor at 18-Sep-07 16:00
memberJames S. Taylor18-Sep-07 16:00 
GeneralEvents in C# to be handled in VB Pin
indivp at 5-Jun-05 8:21
memberindivp5-Jun-05 8:21 
QuestionDelegates sufficient for event-handling? Pin
Andrew Phillips at 24-May-04 22:09
memberAndrew Phillips24-May-04 22:09 
AnswerRe: Delegates sufficient for event-handling? Pin
Nishant S at 24-May-04 22:37
staffNishant S24-May-04 22:37 
GeneralRe: Delegates sufficient for event-handling? Pin
evildictaitor at 10-Sep-06 13:58
memberevildictaitor10-Sep-06 13:58 
QuestionUsing a this reference doesn't work? Pin
Aaron R> at 9-May-03 4:47
memberAaron R>9-May-03 4:47 
AnswerRe: Using a this reference doesn't work? Pin
Nishant S at 9-May-03 17:27
editorNishant S9-May-03 17:27 
GeneralRe: Using a this reference doesn't work? Pin
Aaron R> at 12-May-03 7:17
memberAaron R>12-May-03 7:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150427.1 | Last Updated 17 Oct 2001
Article Copyright 2001 by Nish Nishant
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid