Event Handling
Normally, a user interacts with an application's GUI to indicate the tasks that the application should perform. For example, when you write an e-mail in an e-mail application, clicking the Send button tells the application to send the e-mail to the specified e-mail addresses. GUIs are event driven. When the user interacts with a GUI component, the interactionknown as an eventdrives the program to perform a task. Common events (user interactions) that might cause an application to perform a task include clicking a Button, typing in a TextBox, selecting an item from a menu, closing a window and moving the mouse. A method that performs a task in response to an event is called an event handler, and the overall process of responding to events is known as event handling.
13.3.1. A Simple Event-Driven GUI
The Form in the application of Fig. 13.5 contains a Button that a user can click to display a MessageBox. You have already created several GUI examples that execute an event handler in response to clicking a Button. In this example, we discuss Visual Studio's auto-generated code in more depth.
Figure 13.5. Simple event-handling example using visual programming.
(This item is displayed on page 602 in the print version)
1 // Fig. 13.5: SimpleEventExampleForm.cs 2 // Using Visual Studio to create event handlers. 3 using System; 4 using System.Windows.Forms; 5 6 // Form that shows a simple event handler 7 public partial class SimpleEventExampleForm : Form 8 { 9 // default constructor 10 public SimpleEventExampleForm() 11 { 12 InitializeComponent(); 13 } // end constructor 14 15 // handles click event of Button clickButton 16 private void clickButton_Click( object sender, EventArgs e ) 17 { 18 MessageBox.Show( "Button was clicked." ); 19 } // end method clickButton_Click 20 } // end class SimpleEventExampleForm |
Using the techniques presented earlier in the book, create a Form containing a Button. First, create a new Windows application and add a Button to the Form. In the Properties window for the Button, set the (Name) property to clickButton and the Text property to Click Me. You'll notice that we use a convention in which each variable name we create for a control ends with the control's type. For example, in the variable name clickButton, "Button" is the control's type.
When the user clicks the Button in this example, we want the application to respond by displaying a MessageBox. To do this, you must create an event handler for the Button's Click event. You can create this event handler by double clicking the Button on the Form, which declares the following empty event handler in the program code:
private void clickButton_Click( object sender, EventArgs e ) { } // end method clickButton_Click
By convention, C# names the event-handler method as controlName_eventName (e.g., clickButton_Click). The clickButton_Click event handler executes when the user clicks the clickButton control.
Each event handler receives two parameters when it is called. The firstan object reference named senderis a reference to the object that generated the event. The second is a reference to an event arguments object of type EventArgs (or one of its derived classes), which is typically named e. This object contains additional information about the event that occurred. EventArgs is the base class of all classes that represent event information.
|
To display a MessageBox in response to the event, insert the statement
MessageBox.Show( "Button was clicked." );
in the event handler's body. The resulting event handler appears in lines 1619 of Fig. 13.5. When you execute the application and click the Button, a MessageBox appears displaying the text "Button was clicked".
13.3.2. Another Look at the Visual Studio Generated Code
Visual Studio generates the code that creates and initializes the GUI that you build in the GUI design window. This auto-generated code is placed in the Designer.cs file of the Form (SimpleEventExampleForm.Designer.cs in this example). You can open this file by expanding the node for the file you are currently working in (SimpleEventExampleForm.cs) and double clicking the file name that ends with Designer.cs. Figs. 13.6 and 13.7 show this file's contents. The IDE collapses the code in lines 2153 of Fig. 13.7 by default.
Figure 13.6. First half of the Visual Studio generated code file.
Figure 13.7. Second half of the Visual Studio generated code file.
(This item is displayed on page 604 in the print version)
Now that you have studied classes and objects in detail, this code will be easier to understand. Since this code is created and maintained by Visual Studio, you generally don't need to look at it. In fact, you do not need to understand most of the code shown here to build GUI applications. However, we now take a closer look to help you understand how GUI applications work.
The auto-generated code that defines the GUI is actually part of the Form's classin this case, SimpleEventExampleForm. Line 1 of Fig. 13.6 uses the partial modifier, which allows this class to be split among multiple files. Line 55 contains the declaration of the Button control clickButton that we created in Design mode. Note that the control is declared as an instance variable of class SimpleEventExampleForm. By default, all variable declarations for controls created through C#'s design window have a private access modifier. The code also includes the Dispose method for releasing resources (lines 1219) and method InitializeComponent (lines 2751), which contains the code that creates the Button, then sets some of the Button's and the Form's properties. The property values correspond to the values set in the Properties window for each control. Note that Visual Studio adds comments to the code that it generates, as in lines 3133. Line 39 was generated when we created the event handler for the Button's Click event.
Method InitializeComponent is called when the Form is created, and establishes such properties as the Form title, the Form size, control sizes and text. Visual Studio also uses the code in this method to create the GUI you see in design view. Changing the code in InitializeComponent may prevent Visual Studio from displaying the GUI properly.
|
13.3.3. Delegates and the Event-Handling Mechanism
The control that generates an event is known as the event sender. An event-handling methodknown as the event receiverresponds to a particular event that a control generates. When the event occurs, the event sender calls its event receiver to perform a task (i.e., to "handle the event").
The .NET event-handling mechanism allows you to choose your own names for event-handling methods. However, each event-handling method must declare the proper parameters to receive information about the event that it handles. Since you can choose your own method names, an event sender such as a Button cannot know in advance which method will respond to its events. So, we need a mechanism to indicate which method is the event receiver for an event.
Delegates
Event handlers are connected to a control's events via special objects called delegates. A delegate object holds a reference to a method with a signature that is specified by the delegate type's declaration. GUI controls have predefined delegates that correspond to every event they can generate. For example, the delegate for a Button's Click event is of type EventHandler (namespace System). If you look at this type in the online help documentation, you will see that it is declared as follows:
public delegate void EventHandler( object sender, EventArgs e );
This uses the delegate keyword to declare a delegate type named EventHandler, which can hold references to methods that return void and receive two parametersone of type object (the event sender) and one of type EventArgs. If you compare the delegate declaration with clickButton_Click's header (Fig. 13.5, line 16), you will see that this event handler indeed meets the requirements of the EventHandler delegate. Note that the preceding declaration actually creates an entire class for you. The details of this special class's declaration are handled by the compiler.
Indicating the Method that a Delegate Should Call
An event sender calls a delegate object like a method. Since each event handler is declared as a delegate, the event sender can simply call the appropriate delegate when an event occursa Button calls its EventHandler delegate in response to a click. The delegate's job is to invoke the appropriate method. To enable the clickButton_Click method to be called, Visual Studio assigns clickButton_Click to the delegate, as shown in line 39 of Fig. 13.7. This code is added by Visual Studio when you double click the Button control in Design mode. The expression
new System.EventHandler(this.clickButton_Click);
creates an EventHandler delegate object and initializes it with the clickButton_Click method. Line 39 uses the += operator to add the delegate to the Button's Click event. This indicates that clickButton_Click will respond when a user clicks the Button. Note that the += operator is overloaded by the delegate class that is created by the compiler.
You can actually specify that several different methods should be invoked in response to an event by adding other delegates to the Button's Click event with statements similar to line 39 of Fig. 13.7. Event delegates are multicastthey represent a set of delegate objects that all have the same signature. Multicast delegates enable several methods to be called in response to a single event. When an event occurs, the event sender calls every method referenced by the multicast delegate. This is known as event multicasting. Event delegates derive from class MulticastDelegate, which derives from class Delegate (both from namespace System).
13.3.4. Other Ways to Create Event Handlers
In all the GUI applications you have created so far, you double clicked a control on the Form to create an event handler for that control. This technique creates an event handler for a control's default eventthe event that is most frequently used with that control. Typically, controls can generate many different types of events, and each type can have its own event handler. For instance, you already created Click event handlers for Buttons by double clicking a Button in design view (Click is the default event for a Button). However your application can also provide an event handler for a Button's MouseHover event, which occurs when the mouse pointer remains positioned over the Button. We now discuss how to create an event handler for an event that is not a control's default event.
Using the Properties Window to Create Event Handlers
You can create additional event handlers through the Properties window. If you select a control on the Form, then click the Events icon (the lightning bolt icon in Fig. 13.8) in the Properties window, all the events for that control are listed in the window. You can double click an event's name to display the event handler in the editor, if the event handler already exists, or to create the event handler. You can also select an event, then use the drop-down list to its right to choose an existing method that should be used as the event handler for that event. The methods that appear in this drop-down list are the class's methods that have the proper signature to be an event handler for the selected event. You can return to viewing the properties of a control by selecting the Properties icon (Fig. 13.8).
Figure 13.8. Viewing events for a Button control in the Properties window.
13.3.5. Locating Event Information
Read the Visual Studio documentation to learn about the different events raised by a control. To do this, select Help > Index. In the window that appears, select .NET Framework in the Filtered by drop-down list and enter the name of the control's class in the Index window. To ensure that you are selecting the proper class, enter the fully qualified class name as shown in Fig. 13.9 for class System.Windows.Forms.Button. Once you select a control's class in the documentation, a list of all the class's members is displayed. This list includes the events that the class can generate. In Fig. 13.9, we scrolled to class Button's events. Click the name of an event to view its description and examples of its use (Fig. 13.10). Notice that the Click event is listed as a member of class Control, because class Button's Click event is inherited from class Control.
Figure 13.9. List of Button events.
Figure 13.10. Click event details.
Control Properties and Layout
|