Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Daniel Solis - Illustrated C# 2010 - 2010.pdf
Скачиваний:
16
Добавлен:
11.06.2015
Размер:
11.23 Mб
Скачать

CHAPTER 16 EVENTS

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 to use C# events. Windows GUI programming uses events so extensively that there is a standard .NET Framework pattern for using them, which you are strongly encouraged to follow.

The foundation of the standard pattern for event usage is the EventHandler delegate type, which is declared in the System namespace. The declaration of the EventHandler delegate type is shown in the following code:

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.

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

Using the EventArgs Class

The second parameter in the EventHandler delegate type is an object of class EventArgs, which is declared in the System namespace. You might be tempted to think that, since the second parameter is meant for passing data, an EventArgs class object would be able to store data of some sort. You would be wrong.

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. Class object and class EventArgs are the base classes for whatever actual types are used as the parameters. This allows EventHandler to provide a signature that is the lowest common denominator for all events and event handlers, allowing them to have exactly two parameters, rather than having different signatures for each case.

401

CHAPTER 16 EVENTS

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. The name of the class should end in EventArgs. For example, the following code declares a custom class that can store a string in a field called Message:

Custom class name

Base class

 

 

public class MyTCEventArgs: EventArgs

 

{

 

 

public string Message;

 

// Stores a message

public MyTCEventArgs(string s)

// The constructor sets the message.

{

 

 

Message = s;

 

 

}

 

 

}

 

 

402

CHAPTER 16 EVENTS

Using the Custom Delegate

Now that you have a custom class for passing data in the second parameter of your event handlers, you need a delegate type that uses the new custom class. There are two ways you can do this:

The first way is to use a nongeneric delegate. To do this, do the following:

Create a new custom delegate using your custom class type, as shown in the following code.

Use the new delegate name throughout the four other sections of the event code.

Custom delegate name

Custom class

public delegate void MyTCEventHandler (object sender, MyTCEventArgs e);

The second way was introduced with C# 2.0 and uses the generic delegate EventHandler<>. Chapter 19 covers C# generics. To use the generic delegate, do the following, as shown in the code following:

Place the name of the custom class between the angle brackets.

Use the entire string wherever you would have used the name of your custom delegate type. For example, this is what the event declaration would look like:

Generic delegate using custom class

public event EventHandler<MyTCEventArgs> Elapsed;

Event name

Use the custom class and the custom delegate, either nongeneric or generic, in the other four sections of code dealing with the event.

For example, the following code updates the MyTimerClass code to use a custom EventArgs class called MyTCEventArgs and the generic EventHandler<> delegate.

403

CHAPTER 16 EVENTS

public class MyTCEventArgs: EventArgs

{

public string Message;

 

 

 

Declaration of custom class

public MyTCEventArgs(string s) {

 

 

}

Message = s;

 

 

 

 

 

 

 

}

 

 

 

 

 

public class MyTimerClass Generic delegate

 

 

{

 

 

 

 

public event EventHandler<MyTCEventArgs> Elapsed;

// Event declaration

private void OnOneSecond(object source, EventArgs args)

 

{

if (Elapsed != null)

 

 

 

 

 

 

{

 

 

 

 

 

MyTCEventArgs mtcea =

 

Code to raise event

 

new MyTCEventArgs("Message from OnOneSecond");

 

Elapsed(source, mtcea);

 

 

}

}

 

 

 

 

 

 

 

 

 

...

// This code is given at the end of the chapter.

 

}

 

 

 

 

 

class ClassA

 

 

{

 

 

 

 

 

public void TimerHandlerA(object source, MyTCEventArgs args)

Event handler

{

 

 

 

 

Console.WriteLine("Class A Message: {0}", args.Message);

}

}

404

CHAPTER 16 EVENTS

class Program

{

static void Main()

 

{

 

ClassA ca = new

ClassA();

MyTimerClass mc

= new MyTimerClass();

mc.Elapsed +=

// Register handler.

new EventHandler<MyTCEventArgs> (ca.TimerHandlerA);

Thread.Sleep(3250);

}

}

This code produces the following output:

Class A Message: Message from OnOneSecond

Class A Message: Message from OnOneSecond

Class A Message: Message from OnOneSecond

405

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]