Lựa chọn

 Danh mục

 Chi tiết tài nguyên
Step by Step: Event handling in C#
   Đăng bởi: host | Ngày : 01:43 05/12/09 | Xem: 811 |        
Step by Step: Event handling in C#
Introduction
In this step by step article, we look at implementing event handling in C#.
Implementing events
Step 1 - Create an EventArgs class
If you need to pass arguments to the event handler, a specific EventArgs class has to be made. Eventually, a suitable EventArgs class might already be available, but in most cases, you will have to create one to tailor your specific arguments.
If you do not need to pass arguments to the event handler (except the 'sender'), then no subclass of EventArgs is needed. However, note that you should still define the event method with an argument of type System.EventArgs, and then pass System.EventArgs.Empty.
Create the EventArgs subclass as follows:
    publicclass StartEventArgs : System.EventArgs {
        // Provide one or more constructors, as well as fields and
        // accessors for the arguments.
    }
Note: all EventArgs classes should have a name ending on 'EventArgs'.
Step 2 - Create a delegate
For each EventArgs subclass you have created, a matching delegate should be created. Best practice is to declare the EventArgs subclass and the delegate in the same scope (inside the same namespace or inside the same class). A delegate declaration looks pretty much like a method declaration, but in fact, when declaring a delegate, you create a new class, so placing a delegate declaration directly in a namespace is no problem.
When you use the default System.EventArgs class instead of a subclass of it, there is no need to declare a delegate, you can use the System.EventHandler delegate.
You might also decide to create a specific EventArgs subclass, but no delegate for it. In that case, the event will be delcared of type System.EventHandler (or any superclass of your specific EventArgs subclass for which a delegate is available) and casting of the EventArgs argument in the eventhandler method will be needed.
Declare a delegate as follows:
    publicdelegatevoid StartEventHandler(object sender, StartEventArgs e);
Note: all delegate classes used for event handling should have a name ending on 'EventHandler' and should be of type void. (Delegates that are not of type void are not suitable for multicasting and therefore not suitable for event handling.)
Step 3 - Create Events
For each kind of event, an Event is created in the sending class. The event is declared as of type it's delegate. Multiple events can use the same delegate (think of the delegate as a class, and an event as an instance of it):
    publicclass Sender {
 
        publicevent StartEventHandler BeforeStart;
        publicevent StartEventHandler AfterStart;
 
        //...
   
    }
Step 4 - Create OnEvent methods
Although not required, it is a good convention to create protectedvirtual OnEvent methods for your events:
    protectedvirtualvoid OnBeforeStart(StartEventArgs e) {
        if (BeforeStart != null) BeforeStart(this, e);
    }
 
    protectedvirtualvoid OnAfterStart(StartEventArgs e) {
        if (AfterStart != null) AfterStart(this, e);
    }
You can now call this method whenever you want to send the Start event. I.e:
    OnBeforeStart(new StartEventArgs());
Step 5 - Make the event default
When you class represents a component, it is good practice to make the most commonly used event the default event. Add a DefaultEvent attribute in front of your sender class:
    [System.ComponentModel.DefaultEvent("BeforeStart")]
    publicclass Sender : System.ComponentModel.Component {
        //...
Handling events
A add a handler to an event, use the (overloaded) += assignment operator, as in:
    sender.BeforeStart += new StartEventHandler(this.sender_BeforeStart);
To remove the handler, use the (overloaded) -= assignement operator:
    sender.BeforeStart -= new StartEventHandler(this.sender_BeforeStart);
It might look strange to remove a newly created object. In reality, when you remove a handler, the .NET framework will look for a handler using the same handler method, and remove that handler. The newly created object is then garbage collected.
Here, sender_BeforeStart is the method that will handle the event. It looks like:
    privatevoid sender_BeforeStart(object sender, StartEventArgs e) {
        //...
    }
VS.NET generates the handler methodnames by using the fieldname of the sender object (the name of the variable sending events), and concatenate's to it an underscore followed by the name of the event. It is good practice to follow this convention whenever you are handling events of objects that are declared as fields on your class. In other situations, you are free to choose any arbitrary methodname, however avoid names starting by 'On' (to avoid confusion with event sending methods); when in lack of inspiration, we suggest methods starting with 'Handle' (i.e. HandleBeforeStart).
Code sample
Collapse
publicdelegatevoid StartEventHandler(object sender, StartEventArgs e);
 
publicclass StartEventArgs : System.EventArgs {
    // Provide one or more constructors, as well as fields and
    // accessors for the arguments.
}
 
publicclass Sender {
 
    publicevent StartEventHandler BeforeStart;
    publicevent StartEventHandler AfterStart;
 
    protectedvirtualvoid OnBeforeStart(StartEventArgs e) {
        if (BeforeStart != null) BeforeStart(this, e);
    }
 
    protectedvirtualvoid OnAfterStart(StartEventArgs e) {
        if (AfterStart != null) AfterStart(this, e);
    }
 
    void DoStart() {
        OnBeforeStart(new StartEventArgs());
        //...
        OnAfterStart(new StartEventArgs());
    }
 
    //...
 
}
 
publicclass Receiver {
   
    Sender sender;
 
    public Receiver() {
        sender = new Sender();
    }
 
    void Connect() {
        sender.BeforeStart += new StartEventHandler(this.sender_BeforeStart);
    }
 
    privatevoid sender_BeforeStart(object sender, StartEventArgs e) {
        //...
    }
 
    //...
 
}
About Rudi Breedenraedt

 
Rudi is a Technical Architect at Dolmen.
Click here to view Rudi Breedenraedt's online profile.

 
Bình luận

Thêm nhận xét