Click here to Skip to main content
15,076,740 members
Articles / Programming Languages / C#
Article
Posted 22 Sep 2003

Stats

398.1K views
167 bookmarked

Step by Step: Event handling in C#

Rate me:
Please Sign up or sign in to vote.
4.85/5 (68 votes)
22 Sep 2003Public Domain3 min read
Step by Step guide to implement event handling in C#.

Introduction

In this step by step article, we look at implementing event handling in C#.

Implementing Events

Step 1 - Create an EventArgs Class

If you need to pass arguments to the event handler, a specific EventArgs class has to be made. Eventually, a suitable EventArgs class might already be available, but in most cases, you will have to create one to tailor your specific arguments.

If you do not need to pass arguments to the event handler (except the 'sender'), then no subclass of EventArgs is needed. However, note that you should still define the event method with an argument of type System.EventArgs, and then pass System.EventArgs.Empty.

Create the EventArgs subclass as follows:

C#
public class StartEventArgs : System.EventArgs {
    // Provide one or more constructors, as well as fields and
    // accessors for the arguments.
}

Note: All EventArgs classes should have a name ending on 'EventArgs'.

Step 2 - Create a Delegate

For each EventArgs subclass you have created, a matching delegate should be created. Best practice is to declare the EventArgs subclass and the delegate in the same scope (inside the same namespace or inside the same class). A delegate declaration looks pretty much like a method declaration, but in fact, when declaring a delegate, you create a new class, so placing a delegate declaration directly in a namespace is no problem.

When you use the default System.EventArgs class instead of a subclass of it, there is no need to declare a delegate, you can use the System.EventHandler delegate.

You might also decide to create a specific EventArgs subclass, but no delegate for it. In that case, the event will be declared of type System.EventHandler (or any superclass of your specific EventArgs subclass for which a delegate is available) and casting of the EventArgs argument in the eventhandler method will be needed.

Declare a delegate as follows:

C#
public delegate void StartEventHandler(object sender, StartEventArgs e);

Note: All delegate classes used for event handling should have a name ending on 'EventHandler' and should be of type void. (Delegates that are not of type void are not suitable for multicasting and therefore not suitable for event handling.)

Step 3 - Create Events

For each kind of event, an Event is created in the sending class. The event is declared as of type its delegate. Multiple events can use the same delegate (think of the delegate as a class, and an event as an instance of it):

C#
public class Sender {

    public event StartEventHandler BeforeStart;
    public event StartEventHandler AfterStart;

    //...

}

Step 4 - Create OnEvent Methods

Although not required, it is a good convention to create protected virtual OnEvent methods for your events:

C#
protected virtual void OnBeforeStart(StartEventArgs e) {
    if (BeforeStart != null) BeforeStart(this, e);
}

protected virtual void OnAfterStart(StartEventArgs e) {
    if (AfterStart != null) AfterStart(this, e);
}

You can now call this method whenever you want to send the Start event, i.e.:

C#
OnBeforeStart(new StartEventArgs());

Step 5 - Make the Event Default

When your class represents a component, it is good practice to make the most commonly used event the default event. Add a DefaultEvent attribute in front of your sender class:

C#
[System.ComponentModel.DefaultEvent("BeforeStart")]
public class Sender : System.ComponentModel.Component {
    //...

Handling Events

Add a handler to an event, use the (overloaded) += assignment operator, as in:

C#
sender.BeforeStart += new StartEventHandler(this.sender_BeforeStart);

To remove the handler, use the (overloaded) -= assignment operator:

C#
sender.BeforeStart -= new StartEventHandler(this.sender_BeforeStart);

It might look strange to remove a newly created object. In reality, when you remove a handler, the .NET Framework will look for a handler using the same handler method, and remove that handler. The newly created object is then garbage collected.

Here, sender_BeforeStart is the method that will handle the event. It looks like:

C#
private void sender_BeforeStart(object sender, StartEventArgs e) {
    //...
}

VS.NET generates the handler methodnames by using the fieldname of the sender object (the name of the variable sending events), and concatenates to it an underscore followed by the name of the event. It is good practice to follow this convention whenever you are handling events of objects that are declared as fields on your class. In other situations, you are free to choose any arbitrary methodname, however avoid names starting by 'On' (to avoid confusion with event sending methods); when in lack of inspiration, we suggest methods starting with 'Handle' (i.e., HandleBeforeStart).

Code Sample

C#
public delegate void StartEventHandler(object sender, StartEventArgs e);

public class StartEventArgs : System.EventArgs {
    // Provide one or more constructors, as well as fields and
    // accessors for the arguments.
}

public class Sender {

    public event StartEventHandler BeforeStart;
    public event StartEventHandler AfterStart;

    protected virtual void OnBeforeStart(StartEventArgs e) {
        if (BeforeStart != null) BeforeStart(this, e);
    }

    protected virtual void OnAfterStart(StartEventArgs e) {
        if (AfterStart != null) AfterStart(this, e);
    }

    void DoStart() {
        OnBeforeStart(new StartEventArgs());
        //...
        OnAfterStart(new StartEventArgs());
    }

    //...

}

public class Receiver {
    
    Sender sender;

    public Receiver() {
        sender = new Sender();
    }

    void Connect() {
        sender.BeforeStart += new StartEventHandler(this.sender_BeforeStart);
    }

    private void sender_BeforeStart(object sender, StartEventArgs e) {
        //...
    }

    //...

}

History

  • 23rd September, 2003: Initial version

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication

Share

About the Author

Rudi Breedenraedt
Architect RealDolmen
Belgium Belgium
Rudi is a Software Architect at RealDolmen.

Comments and Discussions

 
GeneralGreat way to explain Event Handlers Pin
AbhishekBafna1826-Jun-15 5:53
MemberAbhishekBafna1826-Jun-15 5:53 
QuestionHow to raise an Event?? Pin
Abhishek_Yadav23-Jun-14 11:18
MemberAbhishek_Yadav23-Jun-14 11:18 
AnswerRe: How to raise an Event?? Pin
Rudi Breedenraedt23-Jun-14 13:56
MemberRudi Breedenraedt23-Jun-14 13:56 
GeneralRe: How to raise an Event?? Pin
Abhishek_Yadav23-Jun-14 19:16
MemberAbhishek_Yadav23-Jun-14 19:16 
GeneralRe: How to raise an Event?? Pin
Rudi Breedenraedt24-Jun-14 11:50
MemberRudi Breedenraedt24-Jun-14 11:50 
GeneralMy vote of 5 Pin
Member 1028931627-May-14 4:58
MemberMember 1028931627-May-14 4:58 
GeneralMy vote of 5 Pin
babatudor4-Jul-13 23:13
Memberbabatudor4-Jul-13 23:13 
GeneralMy vote of 5 Pin
Aayushi Jain2-Jun-13 1:52
MemberAayushi Jain2-Jun-13 1:52 
GeneralMy vote of 5 Pin
Saumitra Kumar Paul3-Dec-12 4:52
MemberSaumitra Kumar Paul3-Dec-12 4:52 
GeneralMy vote of 5 Pin
qiubo22-Oct-12 18:45
Memberqiubo22-Oct-12 18:45 
GeneralMy vote of 5 Pin
MrJamesTK2-Aug-12 7:13
MemberMrJamesTK2-Aug-12 7:13 
GeneralMy vote of 5 Pin
ZeroDigitality27-Sep-11 22:51
MemberZeroDigitality27-Sep-11 22:51 
GeneralMy vote of 5 Pin
sconnor1-Jul-11 10:16
Membersconnor1-Jul-11 10:16 
GeneralClear and concise Pin
la0116-Jun-10 12:11
Memberla0116-Jun-10 12:11 
GeneralRe: Clear and concise Pin
Rudi Breedenraedt16-Jun-10 12:20
MemberRudi Breedenraedt16-Jun-10 12:20 
Questionplz reply Pin
Nazneen Zahid26-Aug-08 0:32
MemberNazneen Zahid26-Aug-08 0:32 
GeneralJust to be sure! Pin
Ingenious00119-Jun-08 1:53
MemberIngenious00119-Jun-08 1:53 
GeneralRe: Just to be sure! Pin
Ingenious00119-Jun-08 3:18
MemberIngenious00119-Jun-08 3:18 
GeneralRe: Just to be sure! Pin
Rudi Breedenraedt19-Jun-08 7:46
MemberRudi Breedenraedt19-Jun-08 7:46 
QuestionSet EventArgs Pin
khTee6-May-08 22:37
MemberkhTee6-May-08 22:37 
Generalsystem wide Pin
styloverte11615-Apr-08 17:04
Memberstyloverte11615-Apr-08 17:04 
GeneralRe: system wide Pin
Rudi Breedenraedt20-Apr-08 0:13
MemberRudi Breedenraedt20-Apr-08 0:13 
Generalbetter question Pin
lew2627-Sep-07 9:32
Memberlew2627-Sep-07 9:32 
GeneralRe: better question Pin
Rudi Breedenraedt27-Sep-07 19:52
MemberRudi Breedenraedt27-Sep-07 19:52 
GeneralQuestion about sender class Pin
lew2627-Sep-07 7:43
Memberlew2627-Sep-07 7:43 
Hello,

I have one question, in the sender class the mthos DoStart where you initialize the public events, do i initialize the events in the sender constructor?

public class sender
{
public sender()
{
this.DoStart(); // or is it optional
}
}
public class receiver
{
................
Sender sender;


public receiver()
{
sender......... += new .......;
sender.DoStart();
}
}

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

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