Library tutorials & articles

New Object-Oriented Capabilities in VB.NET

Events

Events are fully supported within the context of inheritance. If a base class defines a Public event, then that event can be raised by both the code in that base class and from any subclasses derived from that base class.

For instance, we may have a simple base class such as:

Public Class Parent
  Public Event ParentEvent()
  Public Sub DoEvent()
    RaiseEvent ParentEvent()
  End Sub
End Class

It is no surprise that code in this class can raise the ParentEvent event. However, we can then create a subclass such as:

Public Class SubClass
  Inherits Parent
  Public Sub DoSomething()
    RaiseEvent ParentEvent()
  End Sub
End Class

This class is derived from Parent through the use of the Inherits keyword, gaining not only properties and methods, but also events from the base class.

Events can be declared with any scope. Those Private in scope can only be received by the sending object, while those Public in scope can be received by any object. Protected events can only be received by objects created by the defining class or subclasses, while events declared as Friend can be received by any object within the VB.NET project.

Unlike methods, events cannot be overloaded using the Overloads keyword. A class can only define one event with any given name. Since any subclass will automatically gain the event from its parent class, the Overrides keyword makes no sense and cannot be used with events.

Shared Events

Events may be declared as Shared. Shared methods can only raise shared events, not non-shared events. For instance:

Public Class EventSource
  Shared Event SharedEvent()
  Public Shared Sub DoShared()
    RaiseEvent SharedEvent()
  End Sub
End Class

A shared event can be raised by both shared and non-shared methods:

Public Class EventSource
  Public Event TheEvent()
  Shared Event SharedEvent()
  Public Sub DoSomething()
    RaiseEvent TheEvent()
    RaiseEvent SharedEvent()
  End Sub
  Public Shared Sub DoShared()
    RaiseEvent SharedEvent()
  End Sub
End Class

Attempting to raise a non-shared event from a shared method will result in a syntax error.

Raising Events across Projects

In Beta 1, events do not appear to be fully implemented. In particular, events cannot be raised from code in one VB project into code in a separate VB project without some extra work on our part.

The Event and RaiseEvent keywords in VB.NET are actually implemented behind the scenes through the use of delegates. We discussed the Delegate keyword and the concept of delegates in Chapter 3. If we want to raise an event from one VB.NET project and have it be received by code in another project, we’ll have to use a mix of event and delegate concepts.

Implementing the Remote Event Source

While we’ll still use the RaiseEvent statement to raise the event, we need to declare the event somewhat differently if it will be received by code in another VB.NET project. In particular, we need to define the event as a delegate using the Delegate statement – outside the class that will be raising the event.

Create a new Class Library project named EventSource and add a simple class to it named RemoteClass.

Suppose we want to raise an event that returns a String parameter. We’d first declare a delegate with that type of parameter:

Public Delegate Sub RemoteEventHandler(ByVal SomeString As String)

Normally VB.NET automatically creates this delegate for us behind the scenes. However, in Beta 1 this delegate is being created in such a way that it is not available from other projects – thus we must declare it explicitly.

Then, in the same code file, we can create the class that will raise the event:

Public Class RemoteClass
  Public Event RemoteEvent As RemoteEventHandler
  Public Sub DoSomething()
    RaiseEvent RemoteEvent(“My event”)
  End Sub
End Class

The key to success here lies in the declaration of the event itself:

  Public Event RemoteEvent As RemoteEventHandler

The event doesn’t declare its parameters explicitly, instead relying on the delegate to make that declaration. Instead, the event is declared as a specific type – that being the delegate that we just defined.

Beyond that, the code to raise the event is as we’d expect – just a simple RaiseEvent statement:

    RaiseEvent RemoteEvent(“My event”)

It provides the parameter value to be returned as the event is raised.

Receiving the Remote Event

In a separate VB.NET project we can write code to receive the event. Add a Windows Application project to the current solution. Right-click on it and choose the Set As Startup Project option so it will be run when we press F5.

To have access to the class that raises our event, we must add a reference to the EventSource project we just created by using the Project | Add Reference menu option.

With that done, we can add a button to the form and then open the form’s code window. Import the remote namespace:

Imports System.ComponentModel
Imports System.Drawing
Imports System.WinForms
Imports EventSource

In the form’s code we need to declare the remote class using the WithEvents keyword:

Public Class Form1
  Inherits System.WinForms.Form
  Private WithEvents objRemote As RemoteClass

We can now see the event listed in the Method Name dropdown list in the upper-right of the code window when the objRemote entry is selected in the Class Name dropdown in the upper-left. When we select this entry the following code is created:

Public Sub objRemote_RemoteEvent() Handles objRemote.RemoteEvent
End Sub

Unfortunately this code is not correct, as it has no provision for the parameter we’re passing. Strangely enough, the IDE knows this is in error (even though it created the code) and flags it as a syntax error. To fix the problem we just need to add the parameter into the declaration:

Public Sub objRemote_RemoteEvent(ByVal Data As String) _
    Handles objRemote.RemoteEvent
  Messagebox.Show(Data)
End Sub

We’ve also added code to display the result in a dialog. If we add a button to the form with the following code, we can run the project to see the dialog displayed:

Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
  objRemote = New RemoteClass()
  objRemote.DoSomething()
End Sub

Though a bit of extra work in Beta 1, this technique allows us to raise events from one project and have them received by code in another project.

Comments

  1. 12 May 2005 at 01:06

    application level

  2. 04 Nov 2004 at 12:10

    Quote:
    [1]Posted by bsol on 19 Mar 2004 04:06 PM[/1]
    Error in the article "New Object-Oriented Capabilities in VB.NET - Events"


    Derived classes cannot raise base class events in VB.Net. Handle them sure, but not raise them - even if they are declared public. In order to achieve this handle the base class event and raise a derived class event instead.


    B.



    While it is true that VB.NET cannot directly raise events in base classes from a derived class, there is an easy workaround. BTW, in C# you can simply call an event in a base class like: base.onMyEventName(EventArgs e).


    But in VB.NET you cannot use MyBase.EventName() at all. But the workaround is an easy one.
    1) In the base class add an overridable sub that simply raises an event defined in the base class.



    Public MustInherit Class MyClass


     Protected Event MyEventName(ByVal e as EventArgs)


     Protected Overridable Sub OnMyEventName(ByVal e as EventArgs)
         Raiseevent MyEventName(e)
     End Sub


    End Class


    2) In the derived class make a call to the overridable method: Me.OnMyEventName(New EventArgs). It's really just that easy. Do it all the time.


    Have Fun....

  3. 19 Mar 2004 at 16:06

    Error in the article "New Object-Oriented Capabilities in VB.NET - Events"


    Derived classes cannot raise base class events in VB.Net. Handle them sure, but not raise them - even if they are declared public. In order to achieve this handle the base class event and raise a derived class event instead.


    B.

  4. 02 Jul 2003 at 03:14

    How do we read the attributes in an XML file using a DataSet?

  5. 24 Feb 2003 at 08:50

    boig,


    I needed the same thing and found that I have it working using the Public Shared declaration on the class that contains my XMLDocument and the functions to access the document.  This makes the class available across the application.


    Public Shared  oTriggers As Triggers


    If you only need the XMLDocument I would give that a try.


    Hope this helps.

  6. 21 Nov 2002 at 04:46

    I need a global variable; but it is a "XmlDocument" object, does anybody know how do I have to create it, and how to initialitze it?

  7. 01 Nov 2002 at 06:35

    If you set a shared property of a user class in a ASP.NET application, how long wil the value last? Application level? Session level? Page level? Well i was actually looking for an answer to that when i got here...  useful article anyway even though it doesn't answer my question...

  8. 01 Jan 1999 at 00:00

    This thread is for discussions of New Object-Oriented Capabilities in VB.NET.

Leave a comment

Sign in or Join us (it's free).

AddThis

Related jobs

Events coming up

  • Dec 6

    Developing AJAX Web Applications with Castle Monorail

    London, United Kingdom

    Monorail is the model-view-controller engine of the Castle Project, bringing many of the best ideas of Ruby on Rails to the .NET world. In this talk, David De Florinier and Gojko Adzic show how Monorail makes it easy to develop .NET based AJAX applications, and how to use the Castle Project to build Web 2.0 applications effectively. Come to this session if you are a .NET web developer. Everyone is welcome!