Form Inheritance Question

M

Martin Horn

Hi,

I would be grateful if someone can advise me on the following problem I have
encountered.

I have created a test project to demonstrate the problem, it has 2 forms:

Form1, with one button (Button1) on it, as the base class
I have set Button1's modifier to protected
Form 2 inherits Form1

Button1's click event is handled with:
Private Sub Button_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button.Click
Debug.Print("Base Class action")
End Sub

When form2 is shown and Button1 is clicked I want to replace the base class
action for Button1 with something else specific to the child class, and that
is where I have the problem. I have tried the following without success.

In Form2 Create the following sub
Private Sub Button_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button.Click
Debug.Print("Child Class Action")
End Sub

Both the Base Class and Child Class routines are called.

So I amended the Form1 Button click routine to
Protected Overridable Sub Button_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button.Click
Debug.Print("Base Class action")
End Sub

and the Form2 Button Click routine to
Protected Overrides Sub Button_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button.Click
Debug.Print("Child Class Action")
End Sub

And now the base class routine doesn't get called, but the child class
routine executes twice.

Am I missing something obvious, or am I trying to do something that is
fundamentally wrong.

All advice will be appreciated,

Regards,

Martin Horn
 
L

Larry Lard

Martin said:
Hi,

I would be grateful if someone can advise me on the following problem I have
encountered.

I have created a test project to demonstrate the problem, it has 2 forms:

Form1, with one button (Button1) on it, as the base class
I have set Button1's modifier to protected
Form 2 inherits Form1

Button1's click event is handled with:
Private Sub Button_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button.Click
Debug.Print("Base Class action")
End Sub

When form2 is shown and Button1 is clicked I want to replace the base class
action for Button1 with something else specific to the child class

Do this:

In parent form:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Button1Click()
End Sub

Protected Overridable Sub Button1Click()
MsgBox("Parent action")
End Sub

In child form:

Protected Overrides Sub Button1Click()
MsgBox("child action")
End Sub

Voila.

The key thing to remember is that 'Handles' is a VB.NET convenience
that hides much of the 'plumbing' that makes events work. To my mind
it's always best to avoid having more Handles clauses than are
absolutely necessary.

Another way of thinking about it is that what you want the child to
override is not the event *handling* itself, but rather the *response*
to the event - so put the code that does this in a separate sub where
it can be cleanly and 'obviously' overriden.
 
A

Armin Zingler

Martin Horn said:
Hi,

I would be grateful if someone can advise me on the following
problem I have encountered.

I have created a test project to demonstrate the problem, it has 2
forms:

Form1, with one button (Button1) on it, as the base class
I have set Button1's modifier to protected
Form 2 inherits Form1

Button1's click event is handled with:
Private Sub Button_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button.Click
Debug.Print("Base Class action")
End Sub

When form2 is shown and Button1 is clicked I want to replace the
base class action for Button1 with something else specific to the
child class, and that is where I have the problem. I have tried the
following without success.

In Form2 Create the following sub
Private Sub Button_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button.Click
Debug.Print("Child Class Action")
End Sub

Both the Base Class and Child Class routines are called.

So I amended the Form1 Button click routine to
Protected Overridable Sub Button_Click(ByVal sender As
System.Object, _ ByVal e As System.EventArgs) Handles Button.Click
Debug.Print("Base Class action")
End Sub

and the Form2 Button Click routine to
Protected Overrides Sub Button_Click(ByVal sender As System.Object,
_ ByVal e As System.EventArgs) Handles Button.Click
Debug.Print("Child Class Action")
End Sub

And now the base class routine doesn't get called, but the child
class routine executes twice.

Am I missing something obvious, or am I trying to do something that
is fundamentally wrong.

All advice will be appreciated,


'Handles Button.Click' is there twice, thus two event handlers are called.
The difference in example 2 is that the procedure is overridable, therefore
the second call is also to the derived class. That's the expected behavior.

Possible solution:

Base class:

Protected Sub Button_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button.Click
OnButtonClick()
End Sub
protected overridable sub OnButtonClick()
Debug.Print("Base Class action")
end sub


Derived class:
protected overrides sub OnButtonClick
Debug.Print("Derived Class Action")
end sub



Armin
 
H

Herfried K. Wagner [MVP]

Martin,

Martin Horn said:
I would be grateful if someone can advise me on the following problem I
have encountered.

I have created a test project to demonstrate the problem, it has 2 forms:

Form1, with one button (Button1) on it, as the base class
I have set Button1's modifier to protected
Form 2 inherits Form1

Button1's click event is handled with:
Private Sub Button_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button.Click
Debug.Print("Base Class action")
End Sub

When form2 is shown and Button1 is clicked I want to replace the base
class action for Button1 with something else specific to the child class,
and that is where I have the problem. I have tried the following without
success.

Remove the base class' handler and add your own:

\\\
RemoveHandler Me.Button1.Click, AddressOf MyBase.Button1_Click
///
 
M

Martin Horn

Thanks Armin and all others that answered,.

I didn't realise that the event handler association was passed to the
inheriting class, now that I do I have corrected my code and it is working
as I wanted.

Regards,

Martin Horn.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top