Fundamentals of Events

Introduction to Events

An event is something, like an action (but a specific action), that can occur while an object is being used in an application. If such an action or event occurs, the object on which the action occurs must create a notification, like broadcasting a public message in the air, so that the objects that are interested can take appropriate actions.

Various actions (or events) can happen (or occur) to an object at different times in various circumstances. Therefore, an object simply broadcasts that it has, or it makes, some events available, but it doesn't identify what objects would be interested in those events and when. The interested objects decide if and when they may take advantage of a certain event and how they would respond to that action.

To describe it another way, consider an object such as a button on a form. An event is an action, such as a click, that can occur while an object, such as a button, is being used, such as clicked. When such an action, or event, or click, occurs, the object (the button) on which the event occurs must make available a notification so that other objects, such a form or a group box, that are interested can take appropriate actions, such as closing itself (for a form), or displaying a message box.

Practical LearningPractical Learning: Starting a Project

  1. Start Microsoft Visual Studio
  2. In the Visual Studio 2022 dialog box, click Create a New Project
  3. In the Create a New Project wizard page, in the list of projects templates, click Windows Forms App
  4. Click Next
  5. In the Configure Your New Project wizard page, change the Project Name to Exercise5
    Accept or change the project Location
  6. Click Next
  7. In the Framework combo box, accept or select the highest version.
    Click Create
Author Note

Author Note

If you want, using the form of the application you created, you can apply the descriptions in the following sections to experiment with, and get, the same results.

A Delegate for an Event

When creating a class, to indicate that it will use an event, in the source file of that class, create a delegate. The delegate should not return a value. This means that it should be created as void. Here is an example:

delegate void RegularOccurrence();

If you will deal with different events, you can create various delegates.

As you may be aware already, to use a delegate, you must create a function or method that uses the same syntax as the delegate; that is, the same return type (in our case, this would be a void method) with the same number and type(s) of parameter(s). Here is an example:

delegate void RegularOccurrence();

public class Exercise
{
    public void DisplayMessage()
    {
        MessageBox.Show("Your blood will be on your own head!");
    }
}

Of course, the class can contain any member you judge necessary.

Raising an Event

Notifying the other objects about an event is also referred to as raising the event. The object that is raising an event is referred to as the sender. You, as the programmer, must write code that will manage the notification.

An event is created using the event keyword. The basic formula to follow is:

[access-modifiers] event type-name event-name;

The access-modifiers can be one or an appropriate combination of some keywords such as static, public, private, protected, and internal (there are other keywords). The event keyword is required. The type-name is the name of an existing delegate. This means that you must have a delegate that represents the action of the event. Here is an example:

delegate void RegularOccurrence();

public class Exercise
{
    event RegularOccurrence MessageController;

    void DisplayMessage() => MessageBox.Show("Your blood will be on your own head!");
}

Triggerring an Event

In the class that will fire the event, you should create a method that calls the event as if it were a method. The method should be accessible outside the class. Here is an example:

delegate void RegularOccurrence();

public class Exercise
{
    event RegularOccurrence MessageController;

    void DisplayMessage()
    {
        MessageBox.Show("Your blood will be on your own head!");
    }

    public void ApplyMessage()
    {
        MessageController();
    }
}

Handling an Event

Introduction

While an object is being used, it fires one or many events. After creating a method that would manage an event, you must associate that method to the event. This is referred to as handling an event. This association is done using the += operator. This association is also referred to as composition.

Assigning the Name of an Event

Probably the simplest way to associate a method to an event is by assigning the method to the name of the event. Here is an example:

using System.Windows.Forms;

delegate void RegularOccurrence();

public class Exercise
{
    event RegularOccurrence MessageController;

    void DisplayMessage()
    {
        MessageBox.Show("Your blood will be on your own head!");
    }

    void ApplyMessage()
    {
        MessageController();
    }

    public Exercise()
    {
        MessageController += DisplayMessage;

        ApplyMessage();
    }
}

public class Program
{
    public static int Main()
    {
        Exercise exo = new Exercise();
        return 0;
    }
}

Composing an Event Using its Delegate Handler

You can compose an event using the delegate that manages it and passing the name of the method as argument. Here is an example:

using System.Windows.Forms;

delegate void RegularOccurrence();

public class Exercise
{
    event RegularOccurrence MessageController;

    void DisplayMessage()
    {
        MessageBox.Show("Your blood will be on your own head!");
    }

    void ApplyMessage()
    {
        MessageController();
    }

    public Exercise()
    {
        MessageController += new RegularOccurrence(DisplayMessage);

        ApplyMessage();
    }
}

public class Program
{
    public static int Main()
    {
        Exercise exo = new Exercise();
        return 0;
    }
}

Composing an Event Using a Lambda Expression

The previous two techniques require that you first create a method that would be associated with an event. An alternative is to implement the method locally where the event is used. Such an implementation is done as a lambda expression. Here is an example:

using System.Windows.Forms;

delegate void RegularOccurrence();

public class Exercise
{
    event RegularOccurrence MessageController;  

    void ApplyMessage()
    {
        MessageController();
    }

    public Exercise()
    {
        MessageController += () => {MessageBox.Show("Your blood will be on your own head!");};

        ApplyMessage();
    }
}

public class Program
{
    public static int Main()
    {
        Exercise exo = new Exercise();
        return 0;
    }
}

Composing an Event from a Delegate Variable

You can first declare a variable using the delegate and initializing it using the delegate as a class. In the parentheses, enter the name of the method that is associated to the delegate. Here is an example:

delegate void RegularOccurrence();

public class Exercise
{
    event RegularOccurrence MessageController;

    void DisplayMessage()
    {
        MessageBox.Show("Your blood will be on your own head!");
    }

    void ApplyMessage()
    {
        MessageController();
    }

    public Exercise()
    {
        RegularOccurrence ro = new RegularOccurrence(DisplayMessage);
    }
}

You can then assign that variable to the event. This can be done as follows:

using System.Windows.Forms;

delegate void RegularOccurrence();

public class Exercise
{
    event RegularOccurrence MessageController;

    void DisplayMessage()
    {
        MessageBox.Show("Your blood will be on your own head!");
    }

    void ApplyMessage()
    {
        MessageController();
    }

    public Exercise()
    {
        RegularOccurrence ro = new RegularOccurrence(DisplayMessage);

        MessageController += ro;

        ApplyMessage();
    }
}

public class Program
{
    public static int Main()
    {
        Exercise exo = new Exercise();
        return 0;
    }
}

Techniques of Creating an Event

Populating the Method of an Event

The method that manages an event is primarily a function like any other. This means that you can perform in it any regular operation of a method. For example, you can declare and use variables in it. When the method is accessed or called, the code in its body would execute.

A Parameter for an Event

A method that is associated with the delegate of an event can use a parameter. When creating such a method, provide a parameter to the delegate, to the method that implements the event, and to the method that triggers the event. In the body of the method that implements the event, use the parameter any appropriate way you want. Otherwise, you can ignore the parameter. When calling the method that triggers the event, you must pass an argument for the parameter. Here is an example:

using System.Windows.Forms;

delegate void CustomizedHandler(string str);

public class Exercise
{
    event CustomizedHandler MessageController;

    void DisplayMessage(string msg)
    {
        MessageBox.Show(msg, "Exercise");
    }

    void ApplyMessage(string word)
    {
        MessageController(word);
    }

    public Exercise()
    {
        MessageController += DisplayMessage;

        ApplyMessage("He accumulated charriots and horses.");
    }
}

public class Program
{
    static int Main()
    {
        Exercise exo = new Exercise();
        return 0;
    }
}

In the above example, we passed a parameter as a string, as a primitive type. Indeed, the parameter can be any type you want, including a class. Here is an example that uses a form:

using System.Windows.Forms;

delegate void CustomizedHandler(Messaging x);

public class Exercise
{
    event CustomizedHandler CreationController;

    void CreateMessage(Messaging example)
    {
    }

    void Initiate(Messaging example)
    {
        CreationController(example);
    }

    public Exercise()
    {
        CreationController += CreateMessage;

        Messaging walk = new Messaging();

        Initiate(walk);
    }
}

class Program
{
    static void Main()
    {
        Exercise exo = new Exercise();
    }
}

class Messaging
{
    public Messaging()
    {
        MessageBox.Show("Never let your head hang down. Never give up and sit down " +
                        "and grieve. Find another way. And don't pray when it rains " +
                        "if you don't pray when the sun shines. - President Nixon -",
                        "Citations");
    }
}

The parameter can be any type you want, including a class, a tuple, etc, anything you judge necessary.

If you are planning to use just about any object and you don't want to identify it in the beginning, you can create the parameter as object. In the body of the method that implements the event, you can use or ignore the parameter. When calling the method that triggers the event, if you are not using the parameter, you can pass it as null. Here is an example:

using System.Windows.Forms;

delegate void CustomizedHandler(object o);

public class Exercise
{
    event CustomizedHandler CreationController;

    void Creator(object some)
    {
        MessageBox.Show("Never let your head hang down. Never give up and sit down " +
                        "and grieve. Find another way. And don't pray when it rains " +
                        "if you don't pray when the sun shines. - President Nixon -",
                        "Citations");
    }

    void Initiate(object local)
    {
        CreationController(local);
    }

    public Exercise()
    {
        CreationController += Creator;

        Initiate(null);
    }
}

class Program
{
    static void Main()
    {
        Exercise exo = new Exercise();
    }
}

By tradition, if the parameter is of type object, it is named sender. Here is an example:

using System.Windows.Forms;

delegate void CustomizedHandler(object o);

public class Exercise
{
    event CustomizedHandler CreationController;

    void Creator(object sender)
    {
        MessageBox.Show("Never let your head hang down. Never give up and sit down " +
                        "and grieve. Find another way. And don't pray when it rains " +
                        "if you don't pray when the sun shines. - President Nixon -",
                        "Citations");
    }

    void Initiate(object local)
    {
        CreationController(local);
    }

    public Exercise()
    {
        CreationController += Creator;

        Initiate(null);
    }
}

class Program
{
    static void Main()
    {
        Exercise exo = new Exercise();
    }
}

Remember that you can implement an event using a lambda expression. If the event is using a parameter, make sure you pass an argument in the parentheses. You can use the delegate keyword. Here is an example:

using System.Windows.Forms;

delegate void CustomizedHandler(object o);

public class Exercise
{
    event CustomizedHandler CreationController;

    void Initiate(object local)
    {
        CreationController(local);
    }

    public Exercise()
    {
        CreationController += delegate(object sender)
    	{
            MessageBox.Show("Never let your head hang down. Never give up and sit down " +
                            "and grieve. Find another way. And don't pray when it rains " +
                            "if you don't pray when the sun shines. - President Nixon -",
                            "Citations");
        };

        Initiate(null);
    }
}

class Program
{
    static void Main()
    {
        Exercise exo = new Exercise();
    }
}

Or you can omit the delegate keyword and use the => operator. Here is an example:

using System.Windows.Forms;

delegate void CustomizedHandler(object o);

public class Exercise
{
    event CustomizedHandler CreationController;

    void Initiate(object local)
    {
        CreationController(local);
    }

    public Exercise()
    {
        CreationController += (object sender) =>
    {
            MessageBox.Show("Never let your head hang down. Never give up and sit down " +
                            "and grieve. Find another way. And don't pray when it rains " +
                            "if you don't pray when the sun shines. - President Nixon -",
                            "Citations");
        };

        Initiate(null);
    }
}

class Program
{
    static void Main()
    {
        Exercise exo = new Exercise();
    }
}

In this case, you can omit the data type of the parameter.

An Event With Many Parameters

You can create an event that uses two or more parameters. The parameters can be primitive types or classes. They can be of the same or different types. Pass the same number and types of parameters to the delegate, the method that will be associated with the delegate, the method that will trigger the delegate. In the body of the method that will be associated with the delegate, you can ignore all parameters, you can use only one or only some of the parameters, or you can use all parameters. When accessing the event in the method that will trigger the event, make sure you pass each argument. Here is an example:

using System.Windows.Forms;

delegate void CustomizedHandler(object o, Messaging msg);

public class Exercise
{
    event CustomizedHandler CreationController;

    void Creator(object sender, Messaging m)
    {
        MessageBox.Show("Never let your head hang down. Never give up and sit down " +
                        "and grieve. Find another way. And don't pray when it rains " +
                        "if you don't pray when the sun shines. - President Nixon -",
                        "Citations");
    }

    void Initiate(object local, Messaging acting)
    {
        CreationController(local, acting);
    }

    public Exercise()
    {
        CreationController += Creator;

        Initiate(null, null);
    }
}

class Program
{
    static void Main()
    {
        Exercise exo = new Exercise();
    }
}

class Messaging
{
    public Messaging()
    {
    }
}

If you want to use a lambda expression to implement the event, make sure you put the appropriate number of arguments in the parentheses. You can use the delegate keyword. Here is an example:

using System.Windows.Forms;

delegate void CustomizedHandler(object o, Messaging msg);

public class Exercise
{
    event CustomizedHandler CreationController;

    void Initiate(object local, Messaging acting)
    {
        CreationController(local, acting);
    }

    public Exercise()
    {
        CreationController += delegate(object sender, Messaging m)
        {
            MessageBox.Show("Never let your head hang down. Never give up and sit down " +
                            "and grieve. Find another way. And don't pray when it rains " +
                            "if you don't pray when the sun shines. - President Nixon -",
                            "Citations");
        };

        Initiate(null, null);
    }
}

class Program
{
    static void Main()
    {
        Exercise exo = new Exercise();
    }
}

class Messaging
{
    public Messaging()
    {
    }
}

Or you can omit the delegate keyword to use the => operator. Here is an example:

using System.Windows.Forms;

delegate void CustomizedHandler(object o, Messaging msg);

public class Exercise
{
    event CustomizedHandler CreationController;

    void Initiate(object local, Messaging acting)
    {
        CreationController(local, acting);
    }

    public Exercise()
    {
        CreationController += (object sender, Messaging m) =>
        {
            MessageBox.Show("Never let your head hang down. Never give up and sit down " +
                            "and grieve. Find another way. And don't pray when it rains " +
                            "if you don't pray when the sun shines. - President Nixon -",
                            "Citations");
        };

        Initiate(null, null);
    }
}

class Program
{
    static void Main()
    {
        Exercise exo = new Exercise();
    }
}

class Messaging
{
    public Messaging()
    {
    }
}

Remember that, when using the => operator, you can omit the data types of the parameters.

A Class That Manages an Event

At this time, we know that an event can take a parameter if you judge it necessary. We mentioned that a parameter can be a primitive type, a class, a tuple, anything you decide is necessary. Different events perform different types of actions. Consequently, different events may use different types of data and, sometimes, events may need different arguments.

Imagine an event that uses 3, 4, 5, or even 8 parameters or more. Wherever you access the method of that event, you would have to provide all those values. Here is an example:

using System.Windows.Forms;

delegate void CustomizedHandler(object o, Messaging msg, int nbr, Porter port, bool done);

public class Exercise
{
    event CustomizedHandler CreationController;

    void Creator(object sender, Messaging m, int n, Porter p, bool d)
    {
        MessageBox.Show("Never let your head hang down. Never give up and sit down " +
                        "and grieve. Find another way. And don't pray when it rains " +
                        "if you don't pray when the sun shines. - President Nixon -",
                        "Citations");
    }

    void Initiate(object local, Messaging acting, int number, Porter post, bool caught)
    {
        CreationController(local, acting, number, post, caught);
    }

    public Exercise()
    {
        CreationController += Creator;

        Initiate(null, null, 0, null, false);
    }
}

class Program
{
    static void Main()
    {
        Exercise exo = new Exercise();
    }
}

class Messaging { }

class Porter { }

As an alternative, you can first create a class that would hold all the necessary values. Then you can use that class as the type of the parameter of the delegate and therefore of the event. Here is an example:

using System.Windows.Forms;

delegate void CustomizedHandler(Communicator com);

public class Exercise
{
    event CustomizedHandler CreationController;

    void Creator(Communicator c)
    {
        MessageBox.Show("Never let your head hang down. Never give up and sit down " +
                        "and grieve. Find another way. And don't pray when it rains " +
                        "if you don't pray when the sun shines. - President Nixon -",
                        "Citations");
    }

    void Initiate(Communicator doing)
    {
        CreationController(doing);
    }

    public Exercise()
    {
        CreationController += Creator;

        Initiate(null);
    }
}

public class Program
{
    static void Main() => new Exercise();
}

public class Messaging { }

public class Porter { }

public class Communicator
{
    public object Holdup { get; set; }
    public Messaging Message { get; set; }
    public int Number { get; set; }
    public Porter Port { get; set; }
    public bool Done { get; set; }
}

Events and Classes

The Class that Publishes an Event

During its lifetime, a class raises events that other objects can use. This means that you must create a class for the object that will raise the necessary events. This class is referred to as an event publisher, or simply a publisher. In the class, you must declare an event variable as we have done so far. Of course, the event must be declared from an existing delegate. Here is an example:

delegate void Delegation();

public class Exercise
{
    event Delegation MessageController;
}

In the class, create the method that will be associated to the delegate. Remember that the method must use the same syntax as the delegate. Here is an example:

delegate void Delegation();

public class Exercise
{
    event Delegation MessageController;

    public void CreateMessage()
    {
    }
}

In the method, you must access the event one way or another. One way you can do this is to call the event as a method. Here is an example:

delegate void Delegation();

public class Exercise
{
    event Delegation MessageController;

    void CreateMessage()
    {
        MessageController();
    }
}

You can add any appropriate code you want in the body of the method. In the class, you must provide a way to trigger the event. You can do this by adding a method and calling the previously mentioned method from it. This can be done as follows:

using System.Windows.Forms;

delegate void Delegation();

public class Exercise
{
    event Delegation MessageController;

    void CreateMessage()
    {
        MessageController();

        MessageBox.Show("We are inside the method that manages the event");
    }

    void EventTrigger()
    {
        CreateMessage();
    }
}

In the same way, a class can publish as many events as necessary.

The Subscriber of an Event

After a class has published its event(s), other objects can use that(those) event(s). An object that uses such an event is referred to as a subscriber. Before subscribing to an event, in the class of the subscriber, create a method that uses the same syntax as the delegate of the event. As seen previously, to subscribe to an event, use the += operator to assign the method to the event. This can be done as follows:

using System.Windows.Forms;

public delegate void Delegation();

public class Exercise
{
    public event Delegation MessageController;

    void CreateMessage()
    {
        MessageController();
    }

    void EventTrigger()
    {
        CreateMessage();
    }
}

public class Program
{
    public static void DisplayMessage()
    {
        MessageBox.Show("This is the place to do something inside the actual event.");
    }

    public static void Main()
    {
        Exercise exo = new Exercise();
        exo.MessageController += DisplayMessage;
    }
}

To fire the event, call the method that trigers it. Here is an example:

using System.Windows.Forms;

public delegate void Delegation();

public class Exercise
{
    public event Delegation MessageController;

    public void CreateMessage()
    {
        MessageController();
    }

    public void EventTrigger()
    {
        CreateMessage();
    }
}

public class Program
{
    public static void DisplayMessage()
    {
        MessageBox.Show("This is the place to do something inside the actual event.");
    }

    public static void Main()
    {
        Exercise exo = new Exercise();
        exo.MessageController += DisplayMessage;

        exo.EventTrigger();
    }
}

In the same way, you can create an event that uses one or more parameters, as long as you follow the rules we have already seen. Here is an example that uses two parameters (our example doesn't actually use the parameters):

using System.Windows.Forms;

public delegate void Delegation(int a, string b);

public class Exercise
{
    public event Delegation MessageController;

    public void CreateMessage(int x, string something)
    {
        MessageController(x, something);
        
        MessageBox.Show("We are in the event!");
    }

    public void EventTrigger(int abc, string xyz)
    {
        CreateMessage(abc, xyz);
    }
}

public class Program
{
    public static void DisplayMessage(int some, string thing)
    {
        MessageBox.Show("This is the place to do something inside the actual event.");
    }

    public static void Main()
    {
        Exercise exo = new Exercise();
        exo.MessageController += DisplayMessage;
        exo.EventTrigger(0, "");
    }
}

Handling a Subscriber

Remember that a class only publishes or advertizes its events. It doesn't decide if the event should be used. A subscriber decides if or when it would take advantage of an event. In fact, an event may hardly, if ever, be used. Therefore, before using the code in an event, you can first check whether a subscriber has requested an event. In this case, in the class that publishes the event, in the body of the method that is associated to the delegate, instead of calling the event as a method, declare a variable of the type of the delegate and initialize it with the name of the event. This can be done as follows:

public delegate void Delegation();

public class Exercise
{
    public event Delegation MessageController;

    public void CreateMessage()
    {
        Delegation handler = MessageController;
    }

    public void EventTrigger()
    {
        CreateMessage();
    }
}

As long as no object is trying to use an event, its delegate is said to be null. Therefore, before executing the code of the method associated with a delegate, you can first check whether the variable is null. Obviously if it is null, you don't have to do anything. If it is not, then you can execute the code. This can be done as follows:

using System.Windows.Forms;

public delegate void Delegation();

public class Exercise
{
    public event Delegation MessageController;

    public void CreateMessage()
    {
        Delegation handler = MessageController;

        if (handler != null)
        {
            MessageBox.Show("We are in the event!");
        }
    }

    public void EventTrigger()
    {
        CreateMessage();
    }
}

public class Program
{
    public static void DisplayMessage()
    {
        MessageBox.Show("This is the place to do something inside the actual event.");
    }

    public static void Main()
    {
        Exercise exo = new Exercise();
        exo.MessageController += DisplayMessage;

        exo.EventTrigger();
    }
}

In the conditional statement, to execute the code of the method that triggers the event, call the delegate variable as a method. Here is an example:

using System.Windows.Forms;

public delegate void Delegation();

public class Exercise
{
    public event Delegation MessageController;

    public void CreateMessage()
    {
        Delegation handler = MessageController;

        if (handler != null)
        {
            MessageBox.Show("We are in the event!");
            handler();
        }
    }

    public void EventTrigger()
    {
        CreateMessage();
    }
}

public class Program
{
    public static void DisplayMessage()
    {
        MessageBox.Show("This is the place to do something inside the actual event.");
    }

    public static void Main()
    {
        Exercise exo = new Exercise();
        exo.MessageController += DisplayMessage;

        exo.EventTrigger();
    }
}

By the way, if you want to execute the code before triggerring the event, call the triggerring method before such code. Here is an example:

public void CreateMessage()
{
    Delegation handler = MessageController;

    if (handler != null)
    {
        handler();
    
        // Add code to execute after triggering the event
    }
}

If the event is using one or more parameters, make sure you pass them to the delegate variable. Here is an example:

using System.Windows.Forms;

public delegate void Delegation(int a, string b);

public class Exercise
{
    public event Delegation MessageController;

    public void CreateMessage(int x, string something)
    {
        Delegation handler = MessageController;

        if (handler != null)
        {
            MessageBox.Show("We are in the event!");
            handler(x, something);
        }
    }

    public void EventTrigger(int abc, string xyz)
    {
        CreateMessage(abc, xyz);
    }
}

public class Program
{
    public static void DisplayMessage(int some, string thing)
    {
        MessageBox.Show("This is the place to do something inside the actual event.");
    }

    public static void Main()
    {
        Exercise exo = new Exercise();
        exo.MessageController += DisplayMessage;
        
        exo.EventTrigger(0, "");
    }
}

Events in the .NET Framework

The Arguments of an Event

As mentioned previously, if you want to create an event that uses many parameters, you can create a class and use it as the parameter of the delegate. Then use that class in the methods used to implement the event. This would be done as follows:

using System.Windows.Forms;

public delegate void CustomizedHandler(Eventually parameter);

public class Exercise
{
    public event CustomizedHandler MessageController;

    public void DisplayMessage(Eventually msg)
    {
    	MessageBox.Show("This method receives an object.");
    }

    public void ApplyMessage(Eventually something)
    {
		 MessageController(something);
    }

    public Exercise()
    {
		MessageController += DisplayMessage;
    }
}

public class Eventually
{
	//. . . Members
}

public class Program
{
    public static void Main()
    {
        Exercise exo = new Exercise();
    }
}

Instead of, or before, creating a class from scratch to manage one or more events for your application, the .NET Framework provides many classes you can use for events. To start, the library provides a general class that lays a foundation for events. This class is named EventArgs. This is just a simple class used to provide a starting ancestor to event classes. If you want a simple event that doesn't provide any detail other than a default behavior, use the EventArgs class. That is, use this class as the parameter of the delegate, the parameter of the method that will be associated with the delegate, and the method that will trigger the delegate. Here is an example:

using System.Windows.Forms;

public delegate void CustomizedHandler(EventArgs parameter);

public class Exercise
{
    public event CustomizedHandler MessageController;

    public void DisplayMessage(EventArgs msg)
    {
    }

    public void ApplyMessage(EventArgs something)
    {
        MessageController(something);
    }

    public Exercise()
    {
        MessageController += DisplayMessage;
    }
}

public class Program
{
    static void Main()
    {
        Exercise exo = new Exercise();
    }
}

By tradition, the name of the parameter of the EventArgs class is e. Here is an example:

public class Exercise
{
	public void DisplayMessage(EventArgs e)
	{
	}
}

The Name of the Method of an Event

By tradition, the name of the method used for an event starts with On. Here is an example:

public delegate void CustomizedHandler(EventArgs parameter);

public class Exercise
{
    public event CustomizedHandler MessageController;

    public void OnDisplayMessage(EventArgs e)
    {
    }

    public void ApplyMessage(EventArgs something)
    {
        MessageController(something);
    }

    public Exercise()
    {
        MessageController += OnDisplayMessage;
    }
}

An Event With No or Empty Data

An object can fire many events or many types of events. For example, many parts or sections of the same object can be clicked although you would want to do different things depending on the area that was clicked. This means that you can use the same class for many events. If you need different behaviors on the same or various objects, you can create different event classes.

In the method that will be associated to the delegate of an event, we have seen that you can use or ignore its parameter(s), if there is(are) any. In fact, some parameters hold no useable value. To support the ability for an event not to hold any value, the EventArgs class contains a static field named Empty:

public static readonly EventArgs Empty

In fact, this is the only member of that class.

When calling the method that triggers an event in your class, if you don't want or don't plan to use the parameter, you can pass it as null. Here is an example:

using System.Windows.Forms;

public delegate void CustomizedHandler(EventArgs parameter);

public class Exercise
{
    public event CustomizedHandler MessageController;

    public void OnDisplayMessage(EventArgs e)
    {
    }

    public void ApplyMessage(EventArgs something)
    {
        MessageController(something);
    }

    public Exercise()
    {
        this.MessageController += this.OnDisplayMessage;

        ApplyMessage(null);
    }
}

public class Program
{
    public static void Main()
    {
        Exercise exo = new Exercise();
    }
}

Remember that, in the body of the method that will be associated to the delegate, you can use or ignore the parameter. On the other hand, if you want to use the argument, before doing so, you can first find out whether it is empty or not. You use an if conditional statement to find out whether the EventArgs argument is, or is not, equal to EventArgs.Empty. Here is an example:

using System.Windows.Forms;

public delegate void CustomizedHandler(EventArgs parameter);

public class Exercise
{
    public event CustomizedHandler MessageController;

    public void OnDisplayMessage(EventArgs e)
    {
        if (e == EventArgs.Empty)
            MessageBox.Show("This method receives an EventArgs type of parameter but we ain't got no use for it.");
        else // if (e != EventArgs.Empty )
            MessageBox.Show("This method receives an object and we will use it.");
    }

    public void ApplyMessage(EventArgs word)
    {
        MessageController(word);
    }

    public Exercise()
    {
        this.MessageController += this.OnDisplayMessage;

        ApplyMessage(null);
    }
}

public class Program
{
    static void Main()
    {
        Exercise exo = new Exercise();
    }
}

As an alternative, you can find out if the argument is null. Here is an example:

using System.Windows.Forms;

public delegate void CustomizedHandler(EventArgs parameter);

public class Exercise
{
	public event CustomizedHandler MessageController;

	public void OnDisplayMessage(EventArgs e)
	{
		if (e == null)
			MessageBox.Show("This method receives an EventArgs type of parameter but ain't got no use for it.");
	}

	public void ApplyMessage(EventArgs word)
	{
		MessageController(word);
	}

	public Exercise()
	{
		this.MessageController += this.OnDisplayMessage;

		ApplyMessage(null);
	}
}

public class Program
{
	static void Main()
	{
		Exercise exo = new Exercise();
	}
}

In fact, and on the contrary, to use the parameter, you may want to know if it is not null. This can be done as follows:

using System.Windows.Forms;

public delegate void CustomizedHandler(EventArgs parameter);

public class Exercise
{
	public event CustomizedHandler MessageController;

	public void OnDisplayMessage(EventArgs e)
	{
		if (e != null)
			MessageBox.Show("This method receives an object and we will use it.");

	}

	public void ApplyMessage(EventArgs word)
	{
		MessageController(word);
	}

	public Exercise()
	{
		this.MessageController += this.OnDisplayMessage;

		ApplyMessage(null);
	}
}

public class Program
{
	static void Main()
	{
		Exercise exo = new Exercise();
	}
}

Inheriting the Arguments of an Event

As mentioned already, the EventArgs class doesn't give much detail about an event. If you want an event to use one or more values and provide some information to the class that will use that event, you must derive a class from EventArgs. Here is an example:

public class ShapeExtension : EventArgs
{
}

By tradition, the name of the class should end with EventArgs. By default, the new class can be used the same way we used EventArgs. Here is an example:

using System.Windows.Forms;

public class ShapeExtensionEventArgs : EventArgs
{
}

public delegate void CustomizedHandler(ShapeExtensionEventArgs parameter);

public class Exercise
{
    public event CustomizedHandler MessageController;

    public void OnDisplayMessage(ShapeExtensionEventArgs e)
    {
        MessageBox.Show("This method receives an EventArgs type of parameter but ain't got no use for it.");
    }

    public void ApplyMessage(ShapeExtensionEventArgs word)
    {
        MessageController(word);
    }

    public Exercise()
    {
        this.MessageController += this.OnDisplayMessage;

        ApplyMessage(null);
    }
}

public class Program
{
    public static int Main()
    {
        Exercise exo = new Exercise();
        return 0;
    }
}

In the body of the class, you can add members you judge necessary to carry the event. Once again, in the body of the method that will be associated with the event, you can ignore or use the argument. If you decide to use the argument, you can access the members of the event class. Here is an example:

using System.Windows.Forms;

public class ShapeExtensionEventArgs : EventArgs
{
    public int Width { get; set; }
    public int Height { get; set; }
    public string? Text { get; set; }

    public ShapeExtensionEventArgs(string str, int width, int height)
    {
        this.Text = str;
        this.Width = width;
        this.Height = height;
    }
}

public delegate void CustomizedHandler(ShapeExtensionEventArgs parameter);

public class Exercise
{
    public event CustomizedHandler Controller;

    public void OnCreateObject(ShapeExtensionEventArgs e)
    {
        Form display = new Form();

        display.Text = e.Text;
    }

    public void ApplyCreating(ShapeExtensionEventArgs sea)
    {
        Controller(sea);
    }

    public Exercise()
    {
        ShapeExtensionEventArgs e = new ShapeExtensionEventArgs("Notification System", 500, 200);

        this.Controller += this.OnCreateObject;
        ApplyCreating(e);
    }
}

public class Program
{
    public static void Main()
    {
        Exercise exo = new Exercise();
    }
}

The Object that Raised the Events

An event is created and managed by a class but various objects, such as different Windows controls, can use the same event. For example, a form, a button, or a label can be clicked although there is only one class for the click event. In the same way, various objects can fire the same event for the same goal. For example, all radio buttons in the same group or all menu items in the same category are meant to be clicked and sent to the same action. In these and many other cases, you have to be able to identify the object that sent the notification, that is, the object that sent or raised the event. To provide this information, pass an accompanying parameter to the event. To make it possible for any object to be used as this parameter, it should be of type object. By .NET Framework conventions, (1) this parameter precedes that of the event, (2) it is named sender. Here is an example:

using System.Windows.Forms;

public class ShapeExtensionEventArgs : EventArgs
{
    public int Width { get; set; }
    public int Height { get; set; }
    public string? Text { get; set; }

    public ShapeExtensionEventArgs(string str, int width, int height)
    {
        this.Text = str;
        this.Width = width;
        this.Height = height;
    }
}

public delegate void CustomizedHandler(object obj, ShapeExtensionEventArgs parameter);

public class Exercise
{
    public event CustomizedHandler Controller;

    public void OnCreateObject(object sender, ShapeExtensionEventArgs e)
    {
    }

    public void ApplyCreating(object obj, ShapeExtensionEventArgs sea)
    {
        Controller(obj, sea);
    }

    public Exercise()
    {
        ShapeExtensionEventArgs e = new ShapeExtensionEventArgs("Notification System", 500, 200);

        this.Controller += this.OnCreateObject;
    }
}

When calling the method that triggers the event, if you don't want to use or identify the object that is raising the event, you can pass the argument as null. Here is an example:

using System.Windows.Forms;

public class ShapeExtensionEventArgs : EventArgs
{
    public int Width { get; set; }
    public int Height { get; set; }
    public string? Text { get; set; }

    public ShapeExtensionEventArgs(string str, int width, int height)
    {
        this.Text = str;
        this.Width = width;
        this.Height = height;
    }
}

public delegate void CustomizedHandler(object obj, ShapeExtensionEventArgs parameter);

public class Exercise
{
    public event CustomizedHandler Controller;

    public void OnCreateObject(object sender, ShapeExtensionEventArgs e)
    {
        
    }

    public void ApplyCreating(object obj, ShapeExtensionEventArgs sea)
    {
        Controller(obj, sea);
    }

    public Exercise()
    {
        ShapeExtensionEventArgs e = new ShapeExtensionEventArgs("Notification System", 500, 200);

        this.Controller += this.OnCreateObject;
        ApplyCreating(null, e);
    }
}

public class Program
{
    public static void Main()
    {
        Exercise exo = new Exercise();
    }
}

If the method is called in a member of its class, you can pass the argument as this. Here is an example:

. . . No Change

public delegate void CustomizedHandler(object obj, ShapeExtensionEventArgs parameter);

public class Exercise
{
    . . . No Change

    public Exercise()
    {
        ShapeExtensionEventArgs e = new ShapeExtensionEventArgs("Notification System", 500, 200);

        this.Controller += this.OnCreateObject;
        ApplyCreating(this, e);
    }
}

public class Program
{
    public static void Main()
    {
        Exercise exo = new Exercise();
    }
}

A Delegate as an Event Handler

As mentioned previously, you must use a delegate to connect an event to a class. Instead of letting you always create a delegate every time you must manage an event, the .NET Framework provides a large collection of delegates you can directly use. The most fundamental delegate is named EventHandler. This delegate takes two arguments: an object object and an EventArgs object:

public delegate void EventHandler(object sender, EventArgs e)

As you know from the EventArgs class already, if you need to create a simple event that doesn't provide any detail to the external objects, use the EventHandler delegate. Here is an example:

using System.Windows.Forms;

public class Exercise
{
    public event EventHandler FormCreationController;

    public void OnCreateForm(object sender, EventArgs e)
    {
        
    }

    public void Initiate(object obj, EventArgs arg)
    {
        FormCreationController(obj, arg);
    }

    public Exercise()
    {
        FormCreationController += OnCreateForm;

        Initiate(this, null);
    }
}

public class Program
{
    public static void Main()
    {
        Exercise exo = new Exercise();
    }
}

ApplicationPractical Learning: Ending the Lesson


Previous Copyright © 2008-2024, FunctionX Friday 10 June 2022 Next