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
EventArgsclass 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 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