views:

421

answers:

5

Ok, so I have a base class which declares the event StatusTextChanged. My child class, of course cannot directly raise this event.

So I wind up with something like this (for simplicity sake):

Public MustInherit Class FooBase
    Public Event StatusTextChanged(ByVal StatusText As String)
    Protected Sub RaiseStatusTextChangedEvent(ByVal StatusText As String)
        RaiseEvent StatusTextChanged(StatusText)
    End Sub
End Class

And then in the child class I call MyBase.RaiseStatusTextChangedEvent("something"). Is there a better or more recommended way to do this?

edit: VB.NET or C#, either way it works essentially the same.

edit: So after the responses, I'm at this in the base class, then just set the StatusText property in the child class ...

    Public Event StatusTextChanged(ByVal StatusText As String)
    Private _StatusText As String = "Idle."
    Public Property StatusText() As String
        Get
            Return _StatusText
        End Get
        Protected Set(ByVal value As String)
            RaiseEvent StatusTextChanged(value)
        End Set
    End Property
+1  A: 

Unless there is a specific need for your child class to override a base class method then I would say that calling the base class implementation is absolutely the best solution.

Lazarus
To clarify, you mean the way I'm doing it is the best solution? Seems like a bit of redundant code. No overrides on this, at least not that I'd prefer, but I can't declare it NotOverridable because it is not overriding a base method (it is in the base class). Should I clarify the question?
hmcclungiii
Yes, it's explicit and to my mind, more maintainable, than any other implementation. The method exists in the base class, you wouldn't be adding anything to it in the child so be explicit, call the base :)
Lazarus
A: 

This is pretty much the standard way for raising events on a base class via a derived one for this type of scenario.

However this could change a bit depending on who is in control of the StatusText for the hierarchy. If there is a concrete StatusText backing field in FooBase which can only be changed via accessors, then I would not let the child control the raising of the StatusTextChanged event. Instead I would force the raising of the events within the Setter of the property for StatusText. This gives the parent class more control in enforcing any contracts it wants around when to and when not to raise said event.

However if the StatusText is a property which must be defined by the derived class, I would choose the route you displayed.

JaredPar
There isn't a property or even a variable for status text. I really didn't want to expose it. Although I could have a Protected getter/setter for status text, but then that seems like redundant code as well.
hmcclungiii
+2  A: 

I would say that you are rather close to the recommeneded way (or at least the one I would recommend).

I would make a few alterations to your code, given a choice:

  • Make StatusTextChanged Protected Overridable
  • Wrap StatusText in a custom EventArgs class
  • Change the StatusTextChanged declaration into Public Event StatusTextChanged As EventHandler(Of YourCustomEventArgs)

The resulting code:

The custom eventargs class:

Public Class TextEventArgs
    Inherits EventArgs

    Private _text As String

    Public Sub New(ByVal text As String)
        _text = text
    End Sub

    Public ReadOnly Property Text() As String
        Get
            Return _text
        End Get
    End Property

End Class

The event implementation in your base class:

Public Event StatusTextChanged As EventHandler(Of TextEventArgs)
Protected Overridable Sub OnStatusTextChanged(ByVal e As TextEventArgs)
    RaiseEvent StatusTextChanged(Me, e)
End Sub

...and finally a code line for raising the event; either in the base class or a class that inherits it:

OnStatusTextChanged(New TextEventArgs("some text"))

This will be more in line with how events are designed within the rest of the .NET framework.

Fredrik Mörk
Absolutely, the .NET standard for an event handler is Sub EventHandler(sender As System.Object, e As System.EventArgs)
Patrick McDonald
Basically I was just simplifying things for sake of the brevity of the post. Would be nice to just raise the base class event from the child class though. Still seems like a bit of redundant code. Your answer is best so far.
hmcclungiii
A: 

One option you could have is wrap the Status property in the base class, so that it raises the event itself in a change (in C# as dont know VB and dont have access to Visual Studio at the moment)

private string _status;

public string Status
{
    get { return _status; }
    protected set
    {
        if (_status == value) return;
        _status = value;
        StatusChanged(value);
    }
}
JDunkerley
A: 

Here's My code for an event with a delegate and a parameter of status text

Public Event Status As StatusEventHandler

Protected Overridable Sub OnStatus(ByVal e As StatusEventArgs)
    RaiseEvent Status(Me, e)
End Sub

Public Delegate Sub StatusEventHandler(ByVal sender As Object, _
   ByVal e As StatusEventArgs)

<System.Serializable()> _
Public Class StatusEventArgs
    Inherits System.EventArgs

    Public Sub New()
    End Sub

    Public Sub New(ByVal statusText As String)
        _StatusText = statusText
    End Sub

    ' Enter code here for event properties, etc.

    Private _StatusText As String = ""
    Public Property StatusText() As String
        Get
            Return _StatusText
        End Get
        Set(ByVal value As String)
            _StatusText = value
        End Set
    End Property


End Class
Rick Ratayczak