Custom Events

Posted by Sivaraman Dhamodaran Articles | C# Language November 14, 2010
The article talks about what is an event, what is meant by publishing an event and subscribing to the published event. Then it walks throug an example of creating an event and consuming it.
Reader Level:
Download Files:
 

Events an Introduction

An event is kind of 'Something Happened'. Some examples are the button got pressed; a check mark from the check box is removed. We all know that we call this kind of action as events happen to controls.

So let us consider a form that has a button in it. And we all know that a button can be clicked. The user does the action of clicking a button and we do not know when that action will happen. In this situation, if we consider the application wants to know when the button got clicked and wants to say "Hi! There". So what do you think now? Somebody should say button is clicked and somebody should respond to the event in our case saying just a "Hi".

I can hear you say "Not a big deal. Double click the button, the Development environment will bring me to a function, and write the code there that says Hi". Well. If the Team Lead (Yes, the same guy who always bugs you) asks you "Hey! We have a class called Product Stock and it maintains the stock in hand in an integer variable. Can you expose an event say LowStock so that the interested one will get a notification when the stock in hand goes below five?"

What is the answer?  "Yes"? OK, then you already know the Events very well. It is your choice whether you want to refresh it here or not.


If your answer is "Hey. I know how to handle the UI events. I have not created my own event", then this article is for you. Let us start.

Publish and Subscribe

If we go back to the button click on the form that says "Hi there", there are some pieces of information we need to know.

  1. The button is placed on the form. The form is the container that holds the button, which is an UI Component.

  2. The Button class in .Net exposes an event called Click. So button class publishes the event click.

  3. The Form class wants to know when the button got clicked. So it subscribes for the published event Click.

  4. When the Button is clicked, Subscriber for the event Click on the button is notified. And there is handler code that says Hi when the notification is received.

So the publish is nothing but exposing the event and subscribe is kind of getting the notification on the supplied function. Delegate and event are tightly coupled. We will see how when we are going through an example and at the same time you can answer the question for your team lead.

The Example

In this example, we have two classes. One is the ProductStock class, which maintains current stock of the product. The other class is Counter used by the billing counter computers in the retail shop. Let us say a customer comes to the billing counter, purchases a product, then pays the bill and goes to receive the product. Each billing counter receives a notification when the product stock goes low.

Consider the following picture before we move on:

Pic1.jpg  

  1. The ProductStock class publishes the event LowStock

  2. Purchase, Counter etc classes subscribe to the Published event LowStock.

  3. ProductStock sends a notification to the entire subscriber when the ProductStock goes low.

In our Example we are not going to Implement Purchase and Someother class.

The ProductStock Class

1) The ProductStock has two member variables. One to know the product name and another one to keep track of the current stock. The current stock gets reduced by the sales counter when a sale of the product is performed.

//001_1: Member Variable.

public string ProductName;

private int StockInHand;

2) The class declares a multicast delegate OnStockLow that takes an Event source object and EventArgs object. Event source is ProductStock as it is going to raise the notification (Event). EventArgs is usually a class derived from EventArgs that can be used to pass the information related to the event. To keep this example simple I have not derived any object from EventArgs. Below is the declaration of Multicast delegate:

//001_2: Multicast delegate type that get coupled with the event.

public delegate void OnStockLow(object sender, EventArgs e);

3) Next, the event StockLow is declared. Note how the Delegate is coupled with the Event. It implies that notification handler function should return void and receive object as first parameter and EventArgs as second parameter. As it is a multicast delegate you can use delegate chain of above said functions. OK, Now the Product stock published the Event. Below is the declaration of the event:

//001_3: Published event (StockLow), that takes responsibility of sending notification to the scbscriber through the above

//Specified multicast delegate

public event OnStockLow StockLow;

Note the syntax:

public event <delegate type name> <event_name>.

4) The constructor of the ProductStock class initialized the members ProductName and StockInHand. Below is the code:

//001_4: Constructor that Initializes the Stock

public ProductStock(string Name, int OpeningStock)

{

  ProductName = Name;

  StockInHand = OpeningStock;

}

5) The Counter objects calls the ReduceStock function when a sales is performed. This function reduces the current stock and notifies the subscriber of the LowStock event when the current stock goes less than five. Below is the function implementation:

//001_5: This function reduces the stock based on the sales on the billing counters. When the stock in hand is lower than

//                                            5, it raises the event StockLow event.

public void ReduceStock(int SalesDone)

{

            StockInHand = StockInHand - SalesDone;

            if (StockInHand < 5 )

            {

                        EventArgs arg = new EventArgs();

                        StockLow(this, arg);

            }

}

Note that in the above the function call to StockLow(this,arg) is known as raising the event or sending a notification.

We are done with the ProductStock class.

The Counter Class

1) The counter class declares the member variable for the counter name and the constructor initializes the Name. The Sales function takes the ProductStock and number of products sold. It makes a call to the ReduceStock after the sales. Below is the Implementation code:

//002: This class for Sales Counter that performs the Sales on different counters and makes the billing. This class

//                                Subscribe to the Published event and Receives notification through Multicast delegate.

public class Counter

{

            //002_1: Class member

            private string CounterName;

            //002_2: Constructor for Counter

            public Counter(string Name)

            {

                        CounterName = Name;

            }

            //002_2: Function that records the sales performed on the counter

            public void Sales(ProductStock prod, int howmuch)

            {

                        Console.WriteLine("{0} Sold {1} numbers", prod.ProductName, howmuch);

                        prod.ReduceStock(howmuch);

            }

2) Counter class implements the notification handler for StockLow. Note the arguments and the void return type are what is expected by the delegate OnLowStock coupled with the event. Below is the handler:

//002_3: Function that acts as event handler for LowStock to receive the notification

public void LowStockHandler(object Sender, EventArgs e)

{

            Console.WriteLine("Anouncement on {0}: Stock of Product {1} gone Low",

                        CounterName , ((ProductStock) Sender).ProductName );

}

Client Code

Let us see how the client code works. Before that a small review on what we did. The ProductStock class exposes an event StockLow and that event is coupled to OnStockLow delegate. ReduceStock function raises the StockLow event when the product stock goes below five. The counter class implements the notification handler LowStockHandler to receive the notification. Where is the piece of code that links the LowStockHandler to the StockLow event? We will link that in the client code.

1) First the client creates the two billing counter objects. Below is the code for billing counter:

//Client 001: Create Billing Counters

Counter billing_counter1 = new Counter("Sindhu");

Counter billing_counter2 = new Counter("Ganga");

2) Next three ProductStock objects are created. These products will be sold through two counters. Below is code:

//Client 002: Create the Product Stocks

ProductStock prod1 = new ProductStock("Godrej Fridge", 7 );

ProductStock prod2 = new ProductStock("Sony CD Player", 6);

ProductStock prod3 = new ProductStock("Sony DVD", 800);

3) Next, we subscribe to the event LowStock published by the ProductStock class by creating the Delegate that points to the Notification handler function implemented in the Counter class. Below is the code:

//Client 003: Couple the Event with the Handler through the Delegate.

prod1.StockLow += new ProductStock.OnStockLow(billing_counter1.LowStockHandler);

prod2.StockLow += new ProductStock.OnStockLow(billing_counter1.LowStockHandler);

prod1.StockLow += new ProductStock.OnStockLow(billing_counter2.LowStockHandler);

prod2.StockLow += new ProductStock.OnStockLow(billing_counter2.LowStockHandler);  

4) Everything is set up. So let us start selling the products and see the notification when the stock goes below 5. I recommend that you put a break point on the following piece of code and examine how the Events work. Below is the price code:

//Client 004: Now Let us Start serving the customers on the Queue on each counter

billing_counter1.Sales(prod1, 1);

billing_counter2.Sales(prod1, 2);

billing_counter2.Sales(prod3, 70);

billing_counter2.Sales(prod2, 1);

billing_counter1.Sales(prod2, 3);

billing_counter1.Sales(prod3, 5);

Output is shown below

 Pic2.jpg 

Note: The Attached Solution is created in .Net 2003 for backward compatibility. If you have latest version Say "Yes" to the conversion dialog.

COMMENT USING

Trending up