This article explains/describes publisher and subscriber event-handling model with the help of a user control. When we add a user control to a form, we cannot directly handle the events raised by the user control in the form. This can be achieved by using publisher subscriber model, in which we use delegates to publish user control events. I have been introduced to computer languages through .NET. Since I have directly plunged into .NET technology and have not been a part of any other languages, I’m always in awe. (BTW, didn’t somebody say that - to be surprised, to wonder, is to begin to understand). One of the things which I have loved learning is delegates and events, and this article explains just that.
Controls are used to encapsulate discrete units of functionality and provide a graphical representation of that functionality to the user. The .NET Framework provides us with a number of controls. It also allows us to create our own custom controls. Custom controls can be created in 3 ways:
- Inherit from an existing control.
- Inherit from
- Inherit from
In this article, we have used a user control to explain publisher subscriber model, so let's concentrate on that first. The user-designed control is made up of multiple Windows Forms controls that act as a single unit. I.e., .NET gives us an empty control (a rather dull mundane looking container) in which you can drag and drop the Windows Forms controls so that we can reuse the same control on multiple forms.
UserControl class derives from the
ContainerControl class that in turn indirectly derives from the
Control class. So, all we have to do is create a Windows Control project and make a control like this. Now, we add 2 properties to access the height and width values. These properties are specific to this control. We build this control, and now it's ready to be consumed.
Our next task is to use this control. This can be done by creating a Windows Application project and adding a reference to the user control DLL. In the button click event, we can access the user control’s property and thus change the size of the form. That was pretty simple, right?
This control looks fine except that it does not automatically reflect changes. We have to click the button each time we scroll the track bar. The Windows application would look much better without the button click after each change in the track bars. We cannot directly capture the changes/ handle the events because they belong to the individual controls constituting our user control. The individual controls are private to the user control and are not accessible outside. So, now comes the interesting part – i.e. how to publish the events of the private controls.
When any action occurs in an application, it reacts by sending out a message. An event represents this message. i.e. whenever an action occurs, the application raises the event, which sends out the message. Other parts of the application handle the event, which means that a method is executed in response to the event. This method is called the event handler, and it gets information about the events from the arguments passed by the event. All that happens is, when an action occurs, an event notifies other parts of the application: "Hey! Something happened here". Whoever is interested handles it. Now, for the second step…what is the connecting thread between the event and its handler. There comes the job of the delegate. The event delegate is the one that connects the event and the handler. The delegate points to a method that provides the response to the event. In VB.NET, default delegates will be created for events. A delegate is a special class which can store references to methods which matches the signature (function pointer).
Public Delegate Sub HtWtEventHandler(ByVal sender As Object, _
ByVal args As HtWtEventArgs)
Public Event Hello As HtWtEventHandler
We need two elements to raise an event.
- A function pointer to the event handler (delegate -
- A class that has the event data (
Usually, the event data class will be
EventArgs class. In our program, we need to obtain user control specific information, hence we inherit from
EventArgs and have our own event data class. Raising an event is just like making a method call. The existing thread is itself used to run the code in the event handler.
A publisher is the class that implements the event. A subscriber is the class which handles the event raised by the publisher. Whenever the event occurs, the publisher of the event notifies all the subscribers about the event. This is done using:
Protected Function HtWtChanged(ByVal e As HtWtEventArgs)
RaiseEvent Hello(Me, e)
The event member internally manages a linked list of delegates. When an event occurs, it will scan this linked list and invoke the event handler identified by the delegate object for each item in the list.
Thus, to publish and raise an event, a publisher must:
- define a delegate that specifies the signature of the event handler (
- define an event based on the delegate (
- define a method that raises the event (
- invoke the method (
HtWtChanged) when the event occurs
Now that we have published the event, all we have to do is to subscribe to it. In a Windows application, add a reference to this user control. Write a method with the same signature as the delegate. Use the
Handles keyword (or add handler) to make the function handle the event. The event handler is registered with an event by encapsulating the event handler in a delegate object and adding the delegate to the event.
Thus, we have the subscriber handling the event.
Private Sub UserControlEventChanges( _
ByVal sender As Object, _
ByVal args As TestControlEvents.UserControl1.HtWtEventArgs) _
Me.Height = UserControl11.FrmHeight
Me.Width = UserControl11.FrmWidth
This is the flow of the program:
- User--------user clicks on height scroll track bar
- Publisher----private event handler gets called
- Publisher----calls the method
- Publisher----raises the event (
- Subscriber--the event handler in the subscriber gets called
I hope this article gives you a clear understanding of event handling.