It's hard to know for sure because you haven't provided enough information but I suspect that I know what the issue is. When you shadow a member, you MUST access that member via a reference of the derived class in order to invoke the derived implementation. If you use a reference of the base type then it is the base implementation that you will invoke. That is different to when you override a member, in which case the derived implementation will be invoked regardless of the type of the reference. I generally summarise this as overriding following the type of the object while shadowing follows the type of the reference. Try running this code to see that in action:
Module Module1
Sub Main()
Dim dc As New DerivedClass
dc.OverrideMethod()
dc.ShadowMethod()
Dim bc As BaseClass = dc
bc.OverrideMethod()
bc.ShadowMethod()
End Sub
End Module
Public Class BaseClass
Public Overridable Sub OverrideMethod()
Console.WriteLine("BaseClass.OverrideMethod")
End Sub
Public Sub ShadowMethod()
Console.WriteLine("BaseClass.ShadowMethod")
End Sub
End Class
Public Class DerivedClass
Inherits BaseClass
Public Overrides Sub OverrideMethod()
Console.WriteLine("DerivedClass.OverrideMethod")
End Sub
Public Shadows Sub ShadowMethod()
Console.WriteLine("DerivedClass.ShadowMethod")
End Sub
End Class
Here is the output:
DerivedClass.OverrideMethod
DerivedClass.ShadowMethod
DerivedClass.OverrideMethod
BaseClass.ShadowMethod
As you can see, calling the shadowed method via a reference of the base type invokes the base implementation, while calling the overridden method via a reference of the base type invokes the derived implementation.
In your specific case, when you added the instance at run time, you had no field of the control's specific type to access it by, so you probably accessed it via the Controls
collection of the form. That would return a Control
reference so, if you were to access the Enabled
property via that, it would be the base implementation you invoked. If you want to invoke your derived implementation then you'd need to cast that reference as the actual type of your control. One option for doing so is to use the OfType
method to filter by type and cast at the same time, e.g.
Dim firstFancyButton = Controls.OfType(Of FancyButton)().First()
Otherwise, perform an explicit cast, e.g.
Dim firstFancyButton = DirectCast(Controls("FancyButton1"), FancyButton)