Mark Gilbert's Blog

Science and technology, served light and fluffy.

Raising base class events

On one of the forms of my side project, I grouped like controls into a series of custom user controls.  Those user controls all shared a bit of functionality, so I decided to create a user control base class that all of the others inherited from.  All of the common functionality lives in the base class where all of the deriving controls can use it.

One piece of that common functionality was an event called MessageGenerated.  Something would happen in one of the user controls that would generate a message that the user needed to see.  The main form (which contains all of these user controls) has an area where messages are displayed, so I wanted the user controls to raise the event and the main form to handle it.  Seems simple enough.

I put the MessageGenerated declaration in the base class:

Public Event MessageGenerated(ByVal sender As Object, ByVal e As MessageEventArgs)

And then I tried raising the event from one of my user controls:

RaiseEvent MyBase.MessageGenerated(NewSender, New MyBase.MessageEventArgs(NewMessage))

That unfortunately resulted in a compile error:

Derived classes cannot raise base class events.

Yay.  I found another specifically-disallowed feature of .NET.  Yay.

After a bit of research, I came across this article that described why this was not allowed and how to get around it: http://msdn.microsoft.com/en-us/library/hy3sefw3(VS.80).aspx.  The key sentence is here:

When you create a class that can be used as a base class for other classes, you must account for the fact that events are a special type of delegate that can only be invoked from within the class that declared them.

So, the solution (as this article describes) is to provide a Protected method in the base class that wraps RaiseEvent, which allows the derived classes to invoke the event indirectly.  In particular, the methods needs to be “protected virtual void” in C#-ese, or “Protected Overridable Sub” in VB-ese:

Protected Overridable Sub OnMessageGenerated(ByVal NewSender As Object, ByVal NewMessage As String)
    RaiseEvent MessageGenerated(NewSender, New MessageEventArgs(NewMessage))
End Sub

My derived classes can then call MyBase.OnMessageGenerated in place of RaiseEvent.  The main form, then, handles this base class event for each of the controls, allowing me to address each control differently if I needed to:

AddHandler Me.BookFieldGeneralControl.MessageGenerated, AddressOf Me.MessageGeneratedHandler

AddHandler Me.BookFieldNotesCategoriesControl.MessageGenerated, AddressOf Me.MessageGeneratedHandler

AddHandler Me.BookFieldImagesControl.MessageGenerated, AddressOf Me.MessageGeneratedHandler

Advertisements

September 28, 2009 - Posted by | Visual Studio/.NET

4 Comments

  1. […] original post here: Raising base class events « Mark Gilbert's Blog Share and […]

    Pingback by Raising base class events « Mark Gilbert's Blog | September 28, 2009

  2. Thanks, I had a similar requirement and this blog pointed me in the right direction.

    I have shared my approach over at:

    http://asp-net-elephant.blogspot.com/2011/02/capture-page-event-in-web-user-control.html

    Comment by David Grover | February 8, 2011

  3. This post was very helpful and was exactly what was needed. Thanks!

    Comment by Dale Edmondson | May 9, 2011

  4. This was exactly what I was looking for! Thanks, man!

    Comment by Ethan Roberts | October 12, 2012


Sorry, the comment form is closed at this time.

%d bloggers like this: