Event programming for Framework class libraries

Source: Internet
Author: User
Tags definition bind class definition require visual studio
Programming the contents of this page
EventHandler Delegation
Custom event Arguments
Parameterized custom Events
Summary

This month's content is the final installment of a series of three installments devoted to event programming. In the first two installments, I've covered how to define and raise events (see basic instincts:programming with events Using. NET and basic instincts:static event Binding Usin G WithEvents). I also explained how to bind an event handler using dynamic and static event bindings. This month, I'll summarize my introduction to events with some of the more commonly used event handling instances in the Microsoft. NET Framework.

EventHandler Delegation


When you build an application using Windows® forms or ASP.net, you see that a significant percentage of the events encountered is defined based on a generic delegate type named EventHandler. The EventHandler type exists in the System namespace and has the following definition:

Delegate Sub EventHandler (sender as Object, E as EventArgs)

The delegate type EventHandler defines two parameters in its invocation signature. The first parameter (named sender) is based on the generic Object type. The sender parameter is used to pass a reference to the event source object. For example, when a Button object throws an event based on an EventHandler delegate type, it passes as an event source a reference to itself.

The second parameter, defined by EventHandler, is named E, which is an object of type EventArgs. In many cases, the event source passes a parameter value equal to Eventargs.empty, which indicates that there is no additional parameter information. If the event source wants to pass additional parameterized information in the e parameter, it should pass an object created from the derived class of the EventArgs class.

The example shown in Figure 1 contains two event handlers in a Windows forms application that are bound using static event bindings. The Load event of the Form class and the Click event of the Button class are defined according to the delegate type EventHandler.

You should also note that the names and formats of the two event handler methods in Figure 1 are consistent with the Visual Studio. NET IDE for your generation. For example, if you double-click a form or command button in Design view, Visual Studio. NET will automatically create a similar event handler method backbone. All you need to do is populate the implementations of these methods to give your event handlers the expected behavior.

You may notice that the visual Studio. NET IDE generates handler methods using the naming scheme that is required by Visual Basic 6.0. However, you should keep in mind that static event bindings in Visual Basic. NET are not really related to the name of the handler method. It is related to the Handles clause. You can rename the handler method to any name you want at your own discretion.

You can override these two event handlers so that they are bound using dynamic event bindings rather than static event bindings. For example, the class derived from form in Figure 2 provides the exact same event binding behavior as the class derived from form in Figure 1. The only difference is that the latter uses dynamic event bindings and does not require the WithEvents keyword or Handles keyword. In many cases, you will write the implementation of the handler method based on the EventHandler delegate type, rather than referring to the sender parameter or the E parameter. For example, these parameter values do not actually work when you write handlers for the Load events of classes that derive from Form. Sender does not provide any value because it simply passes the Me reference. E parameter pass Eventargs.empty:

Sub Form1_Load (sender as Object, e as EventArgs) Handles MyBase.Load
' * * * These tests are always true
Dim test1 as Boolean = Sender is Me
Dim test2 as Boolean = e is Eventargs.empty
End Sub

You may want to know why the call signature for the Load event did not require more customization for it. After all, if the Load event does not contain any arguments at all, the situation will not be so confusing. It is easy to find an example of another event based on the EventHandler delegate type (and its sender parameter or the e parameter does not pass any value).

Please answer the following questions. If the delegate type has such a generic calling signature, why do you think there are so many events modeled on EventHandler? The designer of the. NET Framework does not model each event based on a custom delegate that has the calling signature appropriate to its needs? As you know, a design goal in. NET Framework development is to limit the number of delegates that are used for event handling. The following are some further explanations.

The first purpose of minimizing the number of delegate types is to make more efficient use of the memory used by the application. Loading more types means consuming more memory. If each event defined by a class in a Windows Forms framework is based on a custom delegate, the hundreds of delegate types must be loaded into memory each time you run a Windows Forms application. Windows forms frameworks can rely on a small number of delegate types to define hundreds of events in the Form class and various control classes to provide better memory utilization.

The second goal of minimizing the number of delegate types is to use pluggable handler methods to increase the likelihood of implementing polymorphism. When you write a handler method by using the calling signature that matches the EventHandler delegate, you can bind it to most events raised by the form and its controls.

Let's look at some examples of writing generic event handlers. Let's start with an example of this: In this example, you can respond to TextChanged events for multiple text boxes in a form by changing the user input to uppercase. There is no need to create separate event handlers for each control. Instead, you can create only one event handler and then bind it to the TextChanged event of several different text boxes (see Figure 3).

For this example, it should be noted first that the Handles clause is not limited to an event. You can include any number of events by using a comma-delimited list after the Handles keyword. In this example, the Textchangedhandler method is used to create three different event handlers. As a result, this method is executed when the user changes the text in any of the three text boxes.

When you execute the Textchangedhandler method, how do you know which TextBox object raised the event? This is the sender parameter to solve the problem. Keep in mind that the sender parameter is passed based on universal type Object. This means that you must convert it to a more specific type before you program it for it. In the previous example, to access the Text property of the sender parameter, you must convert the argument to a TextBox.

If you have used an earlier version of Visual Basic to build a form-based application, you may be accustomed to using a control array. The primary advantage of using control arrays in Visual Basic 6.0 is that this feature makes it possible to create a handler method that responds to events raised by multiple different controls. Visual Basic. NET does not support array of controls. However, you don't need to be overly nervous because, as you've just seen, Visual Basic. NET provides an alternative technology that binds a handler method to multiple different events.

The. NET Framework Event Architecture also provides you with functionality that cannot be implemented by the control array. For example, you can create a handler method to respond to events that are raised by multiple different types of controls. Figure 4 shows an example of a handler method that is bound to three different events on three different control types.

As you can see, the scheme of binding handler methods to events is quite flexible. The only requirement is that the handler method and the event it binds to should be based on the same delegate type. A considerable number of events in the. NET Framework are based on the EventHandler delegate type, making it easy to write common handler methods.

When you write generic handler methods, you sometimes need to write code to perform conditional actions that are performed only when the event source is a particular type of object. For example, your handler method can use the TYPEOF operator to check for sender parameters. This allows your handler method to perform a set of actions when the event source is a Button object, and another set of actions when the event source is a CheckBox object, as follows:

Sub GenericHandler1 (sender as Object, E as EventArgs)
If (TypeOf sender is Button) Then
Dim btn as Button = CType (sender, Button)
' * * * * program against BTN
ElseIf (TypeOf sender is CheckBox) Then
Dim chk as CheckBox = CType (sender, checkbox)
' * * * * program against CHK
End If
End Sub

Back to the top of the page
Custom event Arguments


Event notifications based on EventHandler delegates typically do not send any meaningful information in the E parameter. The e parameter is usually useless because it contains either the Eventargs.empty value or the Nothing value. However, the designers of the. NET Framework created a convention to pass parameterized information to their event handlers. This Convention includes the creation of custom event parameter classes and custom delegate types.

Mouse events raised by the Form class provide a good example of how this convention should be used. The parameterized information about the mouse position and which mouse button is pressed is modeled in a class named MouseEventArgs. The MouseEventArgs class contains the X and Y properties used to track the mouse position, and the Button property that indicates which mouse button is pressed. Note that by convention, the MouseEventArgs class must inherit from the generic class EventArgs.

A convention that passes parameterized information in event notifications requires a custom delegate to supplement the custom event parameter class. Therefore, a delegate named MouseEventHandler is used to supplement the MouseEventArgs class. The handler delegate is defined as follows:

Delegate Sub MouseEventHandler (sender as Object, E as MouseEventArgs)

Now, suppose you want to respond to a mouse-related event, such as a MouseDown event for a Form class. You can write the handler method as shown in Figure 5.

Note that the E parameter is useful in the implementation of this handler method. The e parameter determines the mouse position and which mouse button is pressed. All of these parameterized information can be implemented by designing MouseEventArgs classes.

You can find additional examples of such parameterized conventions that are used in Windows forms frameworks. For example, there is a class named KeyPressEventArgs, which is supplemented by a delegate type named Keypresseventhandler. In addition, the Itemchangedargs class is supplemented by a delegate type named Itemchangedhandler. You may encounter other events whose parameterized information also follows this convention.

Back to the top of the page
Parameterized custom Events


As an exercise, we design a custom event to follow this convention for parameterization. I'll use an example similar to the one I used in recent columns, which includes a BankAccount class. Consider the following code fragment:

Class BankAccount
Sub Withdraw (ByVal Amount as Decimal)
' * * * Send notifications if required
If (Amount > 5000) Then
' * * * Raise Event
End If
' * * * * Perform withdrawal
End Sub
End Class

Suppose the BankAccount object raises an event each time a withdrawal amount is greater than $5,000. When this event is raised, you are asked to pass the withdrawal amount as an argument to all registered event handlers. First, you should create a new event argument class that inherits from the EventArgs class:

Public Class largewithdrawargs:inherits EventArgs
Public Amount as Decimal
Sub New (ByVal Amount as Decimal)
Me.amount = Amount
End Sub
End Class

The custom event parameter class should be designed to contain a public field for each parameterized value that the event source needs to pass to its event handler. In this case, the Largewithdrawargs class is designed to contain a Decimal field named Amount. Next, you must create a new delegate type to complement the new event parameter class:

Delegate Sub Largewithdrawhandler (ByVal sender as Object, _
ByVal e as Largewithdrawargs)

By convention, this delegate type is defined to contain an Object parameter named sender as the first argument. The second parameter, E, is based on the custom event parameter class.

Now that you have created custom event parameter classes and supplemental delegate types, you can put them into use. Consider the following class definition:

Class BankAccount
Public Event Largewithdraw as Largewithdrawhandler
Sub Withdraw (ByVal Amount as Decimal)
' * * * Send notifications if required
If (Amount > 5000) Then
Dim args as New Largewithdrawargs (Amount)
RaiseEvent Largewithdraw (Me, args)
End If
' * * * * Perform withdrawal
End Sub
End Class

It modifies the Largewithdraw event to pass parameterized information in event notifications using the standard conventions in the. NET Framework. When a Largewithdraw event is raised in the withdraw method, it is necessary to create a new instance of the Largewithdrawargs class and pass it as a parameter. Because the BankAccount object raises the event, you can use the ME keyword to pass the sender parameter, as follows:

Dim args as New Largewithdrawargs (Amount)
RaiseEvent Largewithdraw (Me, args)

Now that you've learned how to create an event source, we'll focus on how to create a handler method for this event. The handler method should be able to retrieve the parameterized information it needs through the E parameter. In this case, the handler method uses the E parameter to retrieve the value of the Amount field:

Sub Handler1 (sender as Object, E as Largewithdrawargs)
' * * * * Retrieve parameterized information
Dim Amount as Decimal = E.amount
End Sub

Figure 6 shows the full application, and when a large amount is extracted, the BankAccount object sends an event notification. Note that this application conforms to the standard common language runtime conventions that pass parameterized information in events.

Back to the top of the page
Summary


This section summarizes the basic Knowledge series for event programming using Visual Basic. NET. The first two installments describe the mechanism for raising and handling events. This month's column focuses on programming instances of common events and delegates defined in the. NET Framework.

Most of the events that you handle through visual Basic. NET are most likely based on EventHandler delegates. As you see, you can bind multiple events to one handler method. In this case, it is important to know when and how to use the sender parameter. You also learned about other events that use custom parameter classes to pass parameterized information. In summary, you should now be able to use event-driven frameworks such as Windows forms or ASP. NET) To do some development work.


Please send the questions and comments to Ted to instinct@microsoft.com.

Ted Pattison is the teacher and course author of DevelopMentor (http://www.develop.com). He has written several books about Visual Basic and COM, and he is currently writing a book called Building Applications and components with Visual Basic. NET (Addison-wesley, 2003) of the books.




Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.