In addition to methods and properties, classes can also fire events. It’s possible to raise events from within your classes, although not quite as common. Controls have many events because they expose a visible interface and the user interacts through this interface (clicks, drags and drops, and so on). But classes can also raise events. Class events can come from three different sources:
Progress events – A class might raise an event to indicate the progress of a lengthy process or indicate that an internal variable or property has changed value. The PercentDone event is a typical example. A process that takes a while to complete reports its progress to the calling application with this event, which is fired periodically. These events, which are called progress events, are the most common type of class events.
Time events – Time events are based on a timer. They’re not very common, but you can implement alarms, job schedulers, and similar applications. You can set an alarm for a specific time or an alarm that will go off after a specified interval.
External events – External events, such as the completion of an asynchronous operation, can also fire events. A class might initiate a file download and notify the application when the file arrives.
To fire an event from within a class, you must do the following:
- First you must declare the event and its signature in your class. The declaration must appear in the form, not in any procedure. A simple event, with no arguments, should be declared as follows (ShiftEnd is the name of the event— an event that signals the end of a shift every eight hours):
Public Event ShiftEnd()
- Fire the event from within your class’s code with the RaiseEvent method:
RaiseEvent ShiftEnd()
- That’s all as far as the class is concerned.
- The application that uses the custom class must declare it with the WithEvents keyword. Otherwise, it will still be able to use the class’s methods and properties, but the events raised by the class will go unnoticed. The following statement creates an instance of the class and listens for any event:
Dim WithEvents obj As New Minimal
- Finally, the calling application must provide a handler for the specific event. Because the class was declared with the WithEvents keyword, its name will appear in the list of objects in the editor window and its ShiftEnd event will appear in the list of events (Figure 6.7). Insert the code you want to handle this event in the procedure obj.ShiftEnd.
Figure 6.7 – Programming a custom class’s event
Events usually pass information to the calling application. In VB, all events pass two arguments to the application: a reference to the object that fired the event, and another argument (which is an object and contains information specific to the event).
The arguments of an event are declared just like the arguments of a procedure. The following statement declares an event that’s fired when the class completes the download of a file. The event passes three parameter values to the application that intercepts it:
Public Event CompletedDownload(ByVal fileURL As String, _
ByVal fileName As String, ByVal fileLength As Long)
Code language: VB.NET (vbnet)
The parameters passed to the application through this event are the URL from which the file was downloaded, the path of a file where the downloaded information was stored, and the length of the file. To raise this event from within a class’s code, call the RaiseEvent statement as before, passing three values of the appropriate type, as shown next:
RaiseEvent CompletedDownload("http://www.server.com/file.txt", _
"d:\temp\A90100.txt", 144329)
Code language: VB.NET (vbnet)
When coding the event’s handler, you can access these arguments and use them as you wish. Alternatively, you could create a new object, the DownloadedFileArgument type, and expose these arguments as properties:
Public Class DownloadedFileArgument
Public FileName as String
Public TempLocation As String
Public FileSize As Long
End Class
Code language: VB.NET (vbnet)
Then you can declare the event’s signature by using the DownLoadedFileArgument type in the argument list:
Public Event CompletedDownload(ByVal sender As Object, _
ByVal e As DownloadedFileArgument)
Code language: VB.NET (vbnet)
To fire the CompletedDownload event from within your class’s code, create an instance of the DownLoadedFileArgument class, set its properties and then call the RaiseEvent method, as shown here:
Dim DArgument As New DownloadedFileArgument
DArgument.FileName = "http://www.server.com/file.txt"
DArgument.TempLocation = "d:\temp\A90100.txt"
DArgument.FileSize = 144329
RaiseEvent Fired(Me, DArgument)
Code language: VB.NET (vbnet)
To intercept this event in your test application, declare an object of the appropriate type with the WithEvents keyword and write an event handler for the CompletedDownload event:
Public WithEvents obj As New EventFiringClass
Private Sub obj Fired(ByVal sender As Object, _
ByVal e As Firing.DownloadedFileArgument) _
Handles obj.CompletedDownload
MsgBox("Event fired" & vbCrLf & _
e.FileName & vbCrLf & _
e.TempLocation & vbCrLf & _
e.FileSize.ToString)
End Sub
Code language: VB.NET (vbnet)
That’s all it takes to fire an event from within your custom class. In Chapter, “Building Custom Windows Controls,” you will find several examples of custom events.