Adding Events to Class Modules
Everyone is familiar with the interfaces supported by the objects built into Microsoft Access. A TextBox object, for example, supports ForeColor and BackColor as properties. The DoCmd object provides a wide variety of methods (such as OpenForm) that perform a number of essential actions in Access applications.
Beginning with Access 2000, developers have been able to add events to the class modules in their applications. (Although Access 97 supported class modules with properties and methods, Access 97 didn't provide for custom events in class modules.) Adding events to your class modules is an excellent way to enhance and strengthen the object-oriented elements you add to your applications.
Learning about events in Access
Events are a bit more complex than properties or methods. Even though you constantly use events in your applications, you never see an event (because events don't exhibit a user interface), and under most circumstances, you don't deliberately invoke an event through your code. Events just sort of happen when a user clicks on a command button or tabs off of a control. Events are just there - you use them as needed.
A reasonable analogy for events is the ringer on your cellphone. Your phone rings whenever someone wants to talk to you. The ring alerts you to the incoming call, and you decide whether to respond to the ring or ignore it.
From an object-oriented perspective, you add events to your objects so that the object has some way of notifying its consumer that something has happened within the object or has happened to the object. For example, consider a data-management object that reads and writes data from a data source. The properties are easy to understand and may include the path to the data source, the name of a table, and an ID value to use when extracting or saving data.
In this case, you may add an event to the data-management object that's triggered when the data source is unavailable, or when a record matching the ID value can't be found. Using events is much cleaner and more direct than relying on errors to be thrown when the data-management object fails to complete its task.
Recognizing the need for events
To my knowledge, there is no limit on the number of events you can add to a class module. You declare events in a class module's header, and invoke the events within the class's properties and methods.
This process may make more sense if you consider a property procedure built in the "Adding a new property to provide extra information" section, earlier in this tutorial:
Public Property Get SupplierName() As String Dim varTemp As Variant If m_SupplierID <= 0 Then Exit Property End If varTemp = DLookup("CompanyName", "Suppliers", _ "SupplierID = " & m_SupplierID) If Not IsNull(varTemp) Then SupplierName = CStr(varTemp) End If End Property
This property procedure returns the name of a product supplier, given the SupplierID (notice that the SupplierID is obtained through the class-level m_SupplierID variable). The SupplierName property assumes that the m_SupplierID property variable has already been set through the SupplierID Property Let procedure. The If...End If at the top of this procedure handles cases where the m_SupplierID variable has not been properly set to a value greater than zero.
So far, so good. But, what happens if the SupplierID can't be found in the supplier table? The only way the class's consumer can determine that the supplier does not exist is by examining the value of the SupplierName property. If the SupplierName property is an empty string, the consumer can assume the supplier cannot be found in the supplier table and notify the user accordingly.
The problem with this scheme is that a lot of work is left up to the consumer. The consumer must first set the SupplierID property, then ask for the SupplierName property, and then finally examine SupplierName to see if a nonzero-length string was returned by the SupplierName Property Get.
One of the basic tenets of object-oriented programming is that a class module should encapsulate most, if not all, of the processing required by the entity represented by the class. In the case of the Product class, a consumer shouldn't be required to examine a property's return value to verify its validity. The class should notify the consumer when a problem (such as missing or invalid data) arises within the class.
And, that's one of the primary purposes of events. The InvalidSupplierID event is invoked whenever the class determines that a problem exists with the SupplierID value supplied by the consumer code.
In this tutorial:
- Object-Oriented Programming with VBA
- Introducing Object-Oriented Programming
- Defining objects with class modules
- Adding a class module to a database
- Using the product object
- Creating bulletproof property procedures
- Recognizing the Benefits of Object-Oriented Programming
- Managing a class's interface
- Using Property Procedures
- Exploring property-value persistence
- Modifying the Product Class
- Adding a new property to provide extra information
- Class Events
- The Class_Terminate event procedure
- Adding Events to Class Modules
- Creating custom events
- Trapping custom events
- Exploiting Access class module events