Raise base class event from derived child class - not possible

DolphinPC

Member
Joined
Sep 1, 2023
Messages
8
Programming Experience
5-10
Hello,

I posted on the DotNet reddit with zero feedback. Is it impossible to raise a base class event from a derived (child class that inherits base) class in VB?

This is a trivial request and I am unable to get a subscriber of the event to receive the event.

Many posts online and through MS Docs says to build a base class wrapper that protected sub to call the base class event. This didn't work either. So I tried that.

Consider the following example
(Apologies I'm on mobile - no way to add code tags?


Code Example:
VB.NET:
    Public Class ParentTest
        Public Event OnEventFire()
      
      
        Protected Sub RaiseParentEvent() 'helper sub? See MS article.
            RaiseEvent OnEventFire()
            Debug.Print("Parent event was raised.")
      
        End Sub
      
  
        Public Class ChildTest
            Inherits ParentTest
            Sub EventWasTriggered()
      
                'call parent helper sub
                RaiseParentEvent()
      
            End Sub
      
        End Class
    End Class
VB.NET:
    Class MainProgram
        Private WithEvents parent As New ParentTest
      
      
        Sub RunProgram()
      
            Dim child As New ParentTest.ChildTest
      
            'subscribe to the parent event
            AddHandler parent.OnEventFire, AddressOf ReceiveEvent
      
      
            'trigger event...
            child.EventWasTriggered()
      
        End Sub
      
        'trigger
        Private Sub ReceiveEvent() Handles parent.OnEventFire
            MsgBox("FIRE!")  '<---- never fires when RunProgram() is called!
        End Sub
    End Class
 
When you call the EventWasTriggered method on child reference the event is raised, but ReceiveEvent is not called because you haven't added event handler for the child reference. You have added event handler twice for parent object, both with WithEvents/Handles and AddHandler.
 
When you call the EventWasTriggered method on child reference the event is raised, but ReceiveEvent is not called because you haven't added event handler for the child reference. You have added event handler twice for parent object, both with WithEvents/Handles and AddHandler.

@JohnH

Thank you for your reply.

I do not follow you completely. I am handling the base class event in ReceiveEvent. This event is raised. So I do not fully understand why it's not being handled by ReceieveEvent.
 
You have not added event handler for child.OnEventFire event.
child is the object you raise the event for when you call child.EventWasTriggered method.
 
You have not added event handler for child.OnEventFire event.
child is the object you raise the event for when you call child.EventWasTriggered method.

John,

I am not following. Could you attempt a code example? Child.EventWasTriggered raises its base class event. Which is handled in ReceiveEvent. I don't see where the problem is
 
parent is different object, you have only added event handler for this object, but you have not done anything to raise the event for this object (nor can you since RaiseParentEvent is protected).
If you do AddHandler child.OnEventFire and call child.EventWasTriggered then you will handle the event for child object.
 
Apologies but I'm still not following you.

"but you have not done anything to raise the event for this object"

Yes I have. I have raised it in RaiseParentEvent. It is clearly raised in that protected sub (regardless public or protected the receiver never receives it).

Child calls RaiseParentEvent which the parent event is raised. My receiver handles the event and does not fire
 
It is for child you call this method. ChildTest inherits ParentTest, so all members of ParentTest becomes members of ChildTest. This is how ChildTest class conceptually looks like after inheritance is applied:
VB.NET:
Public Class ChildTest
    Public Event OnEventFire()

    Protected Sub RaiseParentEvent()
        RaiseEvent OnEventFire()
        Debug.Print("Parent event was raised.")
    End Sub

    Sub EventWasTriggered()
        RaiseParentEvent()
    End Sub

End Class
 
It is for child you call this method. ChildTest inherits ParentTest, so all members of ParentTest becomes members of ChildTest. This is how ChildTest class conceptually looks like after inheritance is applied:
VB.NET:
Public Class ChildTest
    Public Event OnEventFire()

    Protected Sub RaiseParentEvent()
        RaiseEvent OnEventFire()
        Debug.Print("Parent event was raised.")
    End Sub

    Sub EventWasTriggered()
        RaiseParentEvent()
    End Sub

End Class

John,

I understand the child inherits the parent event. However did not really consider how this plays a role in raising the parent event.

I still don't understand why the parent event is not being raised. I do not wish to raise a child event from outside the caller. In fact the child class will be private in deployment.

So my question would be

How do I raise the parent even from the child so that the caller can subscribe to the parent event and not be concerned with the child?
 
Doing something to one object will have no effect on another object. You will need a reference to the other object and do something that cause the event to be raised from that object. For example if you have object A and B that have a method RaiseIt that raises an event, then A must call B.RaiseIt for B to raise the event.
 
Doing something to one object will have no effect on another object.
... Unless the object calls a method in the other object, which is called in my child class - to the parent class - which raises the event. If i step through the code, it raises the parent's event, which is subscribe to.... HOWEVER... Perhaps I am onto something... Is what you're describing have something to do with the child 'instance' relative to the parent 'instance'...

As in...

VB.NET:
    Private WithEvents parent As New ParentTest


    Sub RunProgram()

        Dim child As ParentTest.ChildTest 
    
    End Sub
    
    'child variable (instance) has no relationship to variable 'parent'?


Maybe i'm onto what you're saying?... Kind of...

Ultimately, this is my application of this: my goal is to have a nested class (it does not have to inherit - it can use a pointer to the parent) inside a parent class. This child/nested class receives a call to it's function from another source. When I use this entire object, I use the parent. I don't care about the child/nested class. Its job is to only receive outside source data. I want to raise an event to the parent. So that when I use this object, I am subscribing to it's events. While the nested class works internally to support the base class.

I am trying to figure out how I would implement this.






 
child variable (instance) has no relationship to variable 'parent'?
Exactly! Your parent and child are two different objects/instances.
 
Exactly! Your parent and child are two different objects/instances.

Ahh! Im such a dummy. I originally wrote the child class to require a pointer it's parent class instance. Then i said "nah ill just inherit everything". That's what screwed me. Thanks for the help. I was having a hard time understanding. What I don't fully realize is, why does the code step from the child instance, up to the base class? When you instantiate Child = New Parent.Child, there is no parent instance? So why would the child be allowed to even touch the parent - well because its inherited, yes. But if there is no instance of it's parent? Or is there an instance - somewhere?

Here is updated code for anyone interested.


VB.NET:
Public Class ParentTest
    Public Event OnEventFire()

    Protected Sub RaiseParentEvent()
        RaiseEvent OnEventFire()
        Debug.Print("Parent event was raised.")
    End Sub

    Private Class ChildTest
        Private parent As ParentTest ' Reference to the parent instance

        Public Sub New(parent As ParentTest)
            Me.parent = parent
        End Sub

        Sub EventWasTriggered()
            ' Call parent helper sub
            parent.RaiseParentEvent()
        End Sub
    End Class

    ' Create an instance of ChildTest within ParentTest
    Private child As New ChildTest(Me)
End Class

Class MainProgram
    Private WithEvents parent As New ParentTest

    Sub RunProgram()
        ' Subscribe to the parent event
        AddHandler parent.OnEventFire, AddressOf ReceiveEvent

        ' Trigger event from the parent's child instance
        ' in practice this is accessed internally within the parent object
        ' cannot simulate this outside the object...

    End Sub

    ' Triggered when the event is raised from the parent
    Private Sub ReceiveEvent() Handles parent.OnEventFire
        MsgBox("FIRE!") ' This will fire when RunProgram() is called.
    End Sub
End Class
 
What I don't fully realize is, why does the code step from the child instance, up to the base class? When you instantiate Child = New Parent.Child, there is no parent instance?
Because as inherited Child also is a Parent, and more. You can do this:
VB.NET:
Dim c As New Child
Dim p = CType(c, Parent) ' or DirectCast
Here p is still a Child object, but only Parent type members are visible.
 
You seem to have a fundamental lack of understanding of how OOP works. It's not so unusual when starting out. Many people have trouble mapping abstract concepts of types and objects to the real world. Lets try an example that is a bit more like the physical world that might make it easier.

I'm guessing that you understand the concept of buttons and clicking them in GUI programming. There is a Button class and you can add multiple instances of that class to a form. Each of those instances is a distinct object of the same type. If you were to click one of those Button objects with your mouse, you would expect just that Button to raise its Click event, right? Now, let's say that we derive a new class from Button named RedButton that has its BackColor set to Red by default. If you were to add some Button objects and some RedButton objects to a form and then click a RedButton with your mouse, what would you expect to happen? I suspect that you would expect that one RedButton to raise its Click event and ONLY that one RedButton. You wouldn't expect any of the Button objects to raise their Click event, would you? The fact that they are instances of a class inherited by that RedButton's type shouldn;t change that, should it?

Your situation is exactly the same. The fact that the ChildTest class inherits the ParentTest class does not mean that some ParentTest object somewhere should magically raise an event when a ChildTest object does. Why would it?
 
Back
Top