|
A .NET class or interface type
|
ABL class events and .NET class events (also called
.NET events) are very similar in concept, and OpenEdge allows you to manage both of them using the same ABL mechanism. Each class or interface can define any number of class events. Thus, class events are members of the class or interface for which they are defined, like methods, properties, and data members. Like any class member, a class event can be defined as either an instance or a static event, and an instance event can also be defined as abstract. A class event also has an access mode (private, protected, or public), which determines the application scope that can respond to the event.
A class event has a signature, similar to a method, that can define parameters for passing data in response to event notification. An ABL application receives notice of a class event when the object that defines the event
publishes it. In an ABL application, you can subscribe one or more ABL class methods or internal procedures as
event handlers, which execute when a given event is published. These event handlers must all be defined with a signature that is compatible with the event that they are subscribed to handle.
In .NET, Common Language Specification (CLS)-compliant languages, such as C# or Visual Basic, have their own syntax to define events in a .NET class or interface. Similar to any other .NET class member, when you look up information about a .NET event in the .NET class library documentation, it typically describes the event member using syntax from one or more of these .NET languages. For example, C# provides the
event keyword to declare an event in a class definition. In this way, the language-specific syntax for .NET events defines event options that are similar to the ABL DEFINE EVENT statement.
For ABL class events, you define the strongly-typed handler signature in the DEFINE EVENT statement. For .NET events, the handler signature is specified using a .NET class type known as a
delegate that is referenced in the event definition. Thus, using the same delegate type, .NET objects can conveniently define multiple events whose handlers use the same signature. For an ABL class event, you can define either an ABL method signature or you can reference a .NET delegate type to define a .NET signature for the event. Referencing a .NET delegate also allows you to implement a .NET interface event or an inherited .NET abstract event in an ABL class.
To use class events in your application, you must create one or more event handlers. A class event handler can be any class method or internal procedure whose signature is compatible with the signature defined for a given ABL or .NET class event. However, verification of the event handler signature occurs at a different point for method event handlers (at handler subscription compile time) than for internal procedure event handlers (at event publish run time). Note that all class event signatures include a VOID return type; therefore, any event handler method must also have a VOID return type.
If you need to subscribe more than one event handler for an ABL class event, when you publish the event, any OUTPUT or INPUT-OUTPUT parameter you define returns the value set by the final event handler to execute. In addition, any INPUT-OUTPUT parameter you define passes the value set by one event handler as input to the next event handler to execute. A similar effect occurs if you pass a handle or object reference as an INPUT parameter and your event handlers set the value of a public data member on the handle or class-based object. The returned value of the input object data element is the value set by the final handler to execute for the event. In addition, the order of execution for multiple handlers subscribed to a single event is not guaranteed, making it difficult or impossible to know exactly how parameter values returned from the
Publish( ) method have been set. So, if you use more than one handler for a given event, you need to use caution in defining and using the parameters for that event.
If you use a .NET delegate to define an ABL class event, or if you are defining an ABL method or internal procedure as a handler for a .NET event, you must define your event handler signature to match the delegate specified for the event. (In .NET, you implement event handlers by defining derivations of the specified delegate type.) For both ABL class events and .NET events, ABL only supports delegates whose signatures conform to the Microsoft .NET convention for event handler signatures. This signature convention provides for a VOID return type and two INPUT parameters, where the first parameter is a reference to a .NET
System.Object that published the event, and the second parameter is a reference to a .NET
System.EventArgs (or a derived class) that provides event arguments as public members of the class.
VOID EventHandlerName( INPUT sender AS CLASS System.Object,
INPUT args AS CLASS EventArgsClass )
|
Object reference to an event arguments class that contains public properties that provide arguments for the event. Note that for a .NET event,
args references an object that is created by .NET and added to the ABL session object chain when the event handler executes. Like any other locally scoped object reference, if you do not save the value before the event handler terminates, ABL automatically garbage collects this object at some point after the event handler returns.
To identify the exact handler signature for a given .NET delegate, you must look up the delegate in the appropriate class library documentation or use the Class Browser of Progress Developer Studio for OpenEdge to inspect the class. For .NET events supported on the built-in .NET classes provided by OpenEdge and described in the
“Class and Interface Reference” section, each event reference entry described further on in this section indicates the delegate type associated with the event along with its matching event handler signature. Otherwise, to locate the delegate in .NET class library documentation, find the event you want to handle in the documentation for the class that publishes the event. The event definition includes a reference to its delegate type. The documentation for the specified delegate shows the .NET signature you must use for your event handler.
If you do not trap and handle an error raised within a handler for a .NET event, whether it is raised as the ERROR condition or thrown as an error object, the AVM does not throw an
Exception back to .NET, but displays an error message on the default output device and continues processing as if no error had occurred. So, unlike handlers for ABL class events, if you subscribe multiple handlers for a .NET event, all the handlers execute regardless if one or more of them raises an error.
However by convention, a .NET class that defines an event also typically defines a corresponding protected
OnEventName( ) method that allows a derived class to publish the event, where
EventName specifies the name of the .NET event and the signature defines a
System.EventArgs (or derivation) as input. If the
OnEventName( ) method is overrideable (
virtual in C#), you can also override this method in an ABL derived class. If you do override this method, you must also invoke the super class implementation of
OnEventName( ) from within the overriding method (using the
SUPER system reference) in order to ensure that all subscribed .NET delegates also respond to the event. For more information on overriding .NET methods, see the
METHOD statement reference entry.
To allow .NET events from .NET form and control objects to be published as part of the OpenEdge GUI for .NET, you must block to display the .NET forms and allow your subscribed event handlers to execute in response to any published events. To enable this .NET event handling, ABL provides WAIT-FOR statement syntax that blocks for both GUI for .NET events and ABL handle-based object events. For more information, see the
WAIT-FOR statement (.NET and ABL) reference entry.
The reference entries for events that follow appear in alphabetical order by event name. Each reference entry includes the syntax required to define the signature for the event handler as a class-based method, with
EventHandlerName used to indicate a name that you specify for the event handler. If you define the event handler as an internal procedure, define the same number of parameters in order by parameter mode and data type. If the event is a .NET event, the entry description also lists the name of the .NET delegate type defined for the event.