Wednesday, November 14, 2012

Creating Custom Events in C#

First of all, to read and understand this article you should be familiar with these concepts of C# language:

Inheritance
Events

Delegates

Just to remind them very quickly:
Inheritance is a feature of OOP. You can create a class and then you can create another class which has the same properties and methods of the class it is inheriting from. This could be useful for example when you need to create a class for objects like cars. You create a basic Car class and then you create some classes that inherits from Car, and in their body you add methods and/or properties.
The C# syntax for inheriting a class is this:

class BaseClass {

    /*

     body of the BaseClass here

    */

}

class DerivedClass : BaseClass {

    /*

     body of the DerivedClass here

    */

}

Events and delegates are two concepts that very often work together.
When something happens on a windows form (like a click, dblclick, changin some text, selecting an item in a combobox, moving mouse, pressing a key and so on) an event is raised and if you have declared a delegate there is a function that is called to respond to that event.

For example you could want to advice the user that the name he inserted in the textbox is too long.
You add a delegate to the textBox1 objext like this:

this.textBox1.TextChanged += new System.EventHandler(this.HandleChanging);


then declare the HandleChanging method like this:

private void HandleChanging(object sender, System.EventArgs e) {

        // method body here

        }

The concept is: you do an action, an event is raised, and the delegate (if present) calls the proper function to operate on the object that raised the event.

Now, as you probably would know, every object like controls, forms, and so on, has some standard events.
You can add delegates on almost every object for mouse clicks for instance, or Control.Text property changin, making a list here would mean write 200 pages...

But what if you have just created a custom class (for instance a class that inherits from Control) and you want to add to this class a custom property, and also you want that when this property is changed, an event is raised and a delegate is called to launch the proper function to respond to the event?

I mean: I create my Car class and I put inside a tank property.
I want that when tank goes below 5 liters a Change event is raised and advice me that we're going out of fuel.
Let's do this!

Ok we need 3 classes:
- the Car class
- the CarArgs class (for the delegate)
- the Testing class

Let's begin with the CarArgs class:
Here's the code:

// custom attributes

public class CarArgs : System.EventArgs {

       

    private string message;

    public CarArgs(string m) {

        this.message=m;

    }

    public string Message() {

        return message;

    }

}

This class will serve in the declaration of the function we need to call when the event is raised.
It's very simple, a message property, set in the constructor, and a Message() method to retrieve it. Note the inheritance from System.EventArgs.

Now the Car class; here's the code:

// custom object

public class Car {

    private int tank;

    // delegate declaration

    public delegate void ChangingHandler (object sender, CarArgs ca);

    // event declaration

    public event ChangingHandler Change;

       

    public Car(int n) {

        this.tank=n;

    }

    public void SetTank(int p) {

        this.tank=p;

        // call the event

        if (p<5) {

            CarArgs ca=new CarArgs("Tank is below 5, tank value is : "+this.tank);

            Change(this,ca);

        }

    }

    public string GetTank() {

        return this.tank.ToString();

    }

}

This is a little bit more difficult to read.
There is our tank property, then you can see the declaration of a custom delegate ChanginHandler. This is what we have to call when the Change event is raised.
The event declaration follows the delegate's one. Basically we tell the compiler that we want to apply that delegate to that event.
Notice the SetTank() method. If tank goes below 5 litres it raises the event. First it creates CarArgs and then it calls the event Change() passing a pointer to itself (the object) and the CarArgs just created.

Now the testing class: I will report here just the effective code to do the job. You can download the complete source code from my OsiDrive. Here is the link:

 http://zeus.osix.net:80/modules/folder/index.php?tid=6539&action=vf

  • The idea is this: I have created a buttom on a form and when I press it, a car object is being created and tested.

    Here's the code:

    private void button1_Click(object sender, System.EventArgs e) {
            Car car=new Car(50);
            car.Change+=new Car.ChangingHandler(car_Change);
            
            // doesn't raise event
            car.SetTank(40);
            
            // doesn't raise event
            car.SetTank(20);
            
            // raise an event
            car.SetTank(4);
        }

    private void car_Change(object sender, CarArgs ca) {
            MessageBox.Show(ca.Message());
        }

    Very simple: Create the object, associate a delegate to the Change event, provoke the event (the third SetTank() call will provoke the event). You'll see a MessageBox showing and telling you that you're going out of fuel. Just to make sure you have understood let's resume a bit.

    First you must create your custom EventArgs. Create a class that inherits from System.EventArgs and put there all the informations you need when the custom event is raised. Create an object, declare a delegate and an event inside the class and create a method that calls the event. In the testing application, add the delegate to the event, write a function to be called when the event is raised.

    Now what are you wating for? Just go and have fun with Events!
  • from osix.net

    No comments:

    Post a Comment