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
The things to notice about the declaration are the following:
If we modify the
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 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
.
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.
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
Now look at following code and notice what change can be made:
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 EventHandlerreachTen, 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