Pages

Sunday, 28 June 2015

Standard Event Usage

Standard Event Usage

GUI programming is event driven, which means that while the program is running, it can be interrupted at any time by events such as button clicks, key presses, or system timers. When this happens, the program needs to handle the event and then continue on its course.

Clearly, this asynchronous handling of program events is the perfect situation for using C# events. Windows GUI programming uses events so extensively that there is a standard .NET Framework pattern for using them. The foundation of the standard pattern for event usage is the EventHandler delegate type, which is declared in the System namespace. The following line of code shows the declaration of the EventHandler delegate type.
public delegate void EventHandler(object sender, EventArgs e);
The things to notice about the declaration are the following:
  • The first parameter is meant to hold a reference to the object that raised the event. It is of type object and can, therefore, match any instance of any type.
  • The second parameter is meant to hold state information of whatever type is appropriate for the application.
  • The return type is void.
The second parameter in the EventHandler delegate type is an object of class EventArgs, which is declared in the System namespace. It's used to:
  • The EventArgs class is designed to carry no data. It is used for event handlers that do not need to pass data—and is generally ignored by them.
  • If you want to pass data, you must declare a class derived from EventArgs, with the appropriate fields to hold the data you want to pass.
Even though the EventArgs class does not actually pass data, it is an important part of the pattern of using the EventHandler delegate. These parameters, of types object and EventArgs, are the base classes for whatever actual types are used as the parameters. This allows the EventHandler delegate to provide a signature that is the lowest common denominator for all events and event handlers, allowing all events to have exactly two parameters, rather than having different signatures for each case.

If we modify the incrementer program to use the EventHandler delegate, The code will be:
class incrementer
{
 public event EventHandler reachTen, reachDozen, reachFifty, reachHundreds;
 public void startIncrement(int start, int end)
 {
  for (int counter = start; counter <= end; ++counter)
  {
   if ((counter % 10 == 0) && (reachTen != null))
   {
    Console.Write("current counter: " + counter + " ");
    reachTen(this, null);
   }

   if ((counter % 12 == 0) && (reachDozen != null))
   {
    Console.Write("current counter: " + counter + " ");
    reachDozen(this, null);
   }

   if ((counter % 50 == 0) && (reachFifty != null))
   {
    Console.Write("current counter: " + counter + " ");
    reachFifty(this, null);
   }

   if ((counter % 100 == 0) && (reachHundreds != null))
   {
    Console.Write("current counter: " + counter + " ");
    reachHundreds(this, null);
   }
  }
 }
}

class eventSubscriber
{
 public void reachTen(object sender, EventArgs args)
 {
  Console.WriteLine("counting reach Ten");
 }

 public static void reachDozen(object sender, EventArgs args)
 {
  Console.WriteLine("counting reach Dozen");
 }
}

class Program
{
 static void Main(string[] args)
 {
  incrementer myInc = new incrementer();
  eventSubscriber myEvSubs = new eventSubscriber();
  myInc.reachTen += myEvSubs.reachTen;                                            //instance method
  myInc.reachDozen += eventSubscriber.reachDozen;                                 //static method
  myInc.reachFifty += delegate(object sender, EventArgs arguments) { Console.WriteLine("counting reach Fifty"); };  //anonymous method
  myInc.reachHundreds += (sender, arguments) => Console.WriteLine("counting reach Hundreds");         //lambda expressions
  myInc.startIncrement(1, 100);
 }
}

Passing Data by Extending EventArgs

To pass data in the second parameter of your event handler and adhere to the standard conventions, you need to declare a custom class derived from EventArgs that can store the data you need passed. For example:
public class myEventArgs : EventArgs
{
 public int IterationCounter { get; set; }   // Stores an integer
}

Now look at following code and notice what change can be made:
 
public class myEventArgs : EventArgs
{
 public int IterationCounter { get; set; }   // Stores an integer
}

class incrementer
{
 public event EventHandler reachTen, reachDozen, reachFifty, reachHundreds;     //change EventHandler object using generics
 public void startIncrement(int start, int end)
 {
  for (int counter = start; counter <= end; ++counter)
  {
   if ((counter % 10 == 0) && (reachTen != null))
    reachTen(this, new myEventArgs() { IterationCounter = counter });

   if ((counter % 12 == 0) && (reachDozen != null))
    reachDozen(this, new myEventArgs() { IterationCounter = counter });

   if ((counter % 50 == 0) && (reachFifty != null))
    reachFifty(this, new myEventArgs() { IterationCounter = counter });

   if ((counter % 100 == 0) && (reachHundreds != null))
    reachHundreds(this, new myEventArgs() { IterationCounter = counter });
  }
 }
}

class eventSubscriber
{
 public void reachTen(object sender, myEventArgs args)
 {
  Console.Write("current counter: " + args.IterationCounter + " ");
  Console.WriteLine("counting reach Ten");
 }

 public static void reachDozen(object sender, myEventArgs args)
 {
  Console.Write("current counter: " + args.IterationCounter + " ");
  Console.WriteLine("counting reach Dozen");
 }
}

class Program
{
 static void Main(string[] args)
 {
  incrementer myInc = new incrementer();
  eventSubscriber myEvSubs = new eventSubscriber();
  myInc.reachTen += myEvSubs.reachTen;                                            //instance method
  myInc.reachDozen += eventSubscriber.reachDozen;                                 //static method
  myInc.reachFifty += delegate(object sender, myEventArgs arguments)              //anonymous method
   {
    Console.Write("current counter: " + arguments.IterationCounter + " ");
    Console.WriteLine("counting reach Fifty"); 
   };
  myInc.reachHundreds += (sender, arguments) =>
  {
   Console.Write("current counter: " + arguments.IterationCounter + " ");
   Console.WriteLine("counting reach Hundreds");         //lambda expressions
  };
  myInc.startIncrement(1, 100);
 }
}

0 comments:

Post a Comment