Driving me nuts! How to do two-levels inheritance under UserControl?

  • Thread starter Thread starter Jeannot
  • Start date Start date
J

Jeannot

I have a few types of panels (each with different controls), which I
will create dynamically and place on a form.
I can make them UserControls if I need to.

However I would like to have a base class for these, so that I have a
class hierarchy like:

System.Windows.Forms.Panel
|
|
MyBasePanelClassWithOverridableMethods
| |
| |
MyPanelType1 MyPanelType2


I tried to create a UserControl and inserted a base class within
Notepad, changing:

----------------------
Partial Class UserControl1
Inherits System.Windows.Forms.UserControl
---------------------
To:
----------------------
Partial Class MyBaseUserControl
Inherits System.Windows.Forms.UserControl
End Class

Partial Class UserControl1
Inherits Class MyBaseUserControl
------------------------

....and DevStudio2008 gives me an error "Value does not fall within
expected range", which is useless.


Is there something more I need to do to insert my base class?

Is there another way to achieve what I need to achieve? I need
MyPanelType1 and MyPanelType2 to be editable as far as contained
controls, etc...

Thanks!
 
Is that your ACTUAL code (i.e., you copied and pasted)? Because if so, you
need to drop the second "Class":

Partial Class UserControl1
Inherits MyBaseUserControl

You are correct, I made a typo retyping.
My failed attempt looks like what you types, with the second "Class"
removed
 
I have a few types of panels (each with different controls), which I
will create dynamically and place on a form.
I can make them UserControls if I need to.

However I would like to have a base class for these, so that I have a
class hierarchy like:

System.Windows.Forms.Panel
|
|
MyBasePanelClassWithOverridableMethods
| |
| |
MyPanelType1 MyPanelType2

To create MyBasePanel, create a UserControl. Edit the designer.vb
file and change the Inherits line to System.Windows.Forms.Panel. You
will also need to comment out a line further down in the file that
will have a syntax error.

Build your project.

To create MyPanelType1 and MyPanelType2, create an Inherited User
Control and select MyBasePanel as the class to inherit from.
 
To create MyBasePanel, create a UserControl. Edit the designer.vb
file and change the Inherits line to System.Windows.Forms.Panel. You
will also need to comment out a line further down in the file that
will have a syntax error.

Okay, that worked.
Build your project.

That too
To create MyPanelType1 and MyPanelType2, create an Inherited User
Control and select MyBasePanel as the class to inherit from.

I won't let me, MyBasePanel does not show. It asks me to select a base
class for the Inherited User Control, but I have no base class to
select from.
"Warning: No built assemblies contain components to inherit from.
Build the current application, or click Browse and select a previously
built assembly from another application".
 
I tried with a BaseForm, and MyForm1 and MyForm2

The compiler lets me do it, but refuses that I dynamically add a form
inside a form.
 
Okay, that worked.


That too


I won't let me, MyBasePanel does not show. It asks me to select a base
class for the Inherited User Control, but I have no base class to
select from.
"Warning: No built assemblies contain components to inherit from.
Build the current application, or click Browse and select a previously
built assembly from another application".

If you have built the project that includes the base form, and that
project is referenced in the project where you are trying to create
the derived controls, the base class should appear in the list.
 
If you have built the project that includes the base form, and that
project is referenced in the project where you are trying to create
the derived controls, the base class should appear in the list.

Yep. I have cleaned it, rebuilt it, left VS2008, came back, cleaned
it, built it, nothing will do.

Why implementing a class hierarchy based on a Panel is high technology
in 2008, that is beyond me.

Thanks for your help so far.
 
Yep. I have cleaned it, rebuilt it, left VS2008, came back, cleaned
it, built it, nothing will do.

Why implementing a class hierarchy based on a Panel is high technology
in 2008, that is beyond me.

Thanks for your help so far.

I'm sorry, my mistake. Obviously Inherited User Control won't work
because your base control is not based on UserControl.

Create the next level of inheritance exactly like you did the first
one. Create a UserControl and edit the designer.vb file to change the
Inherits line from UserControl to your base class.
 
Jeannot wrote :

"I have a few types of panels (each with different controls), which I will
create dynamically and place on a form. I can make them UserControls if I
need to. ... However I would like to have a base class for these, so that I
have a class hierarchy like: ... snip ... Is there another way to achieve
what I need to achieve? I needMyPanelType1 and MyPanelType2 to be editable
as far as contained controls, etc..."

Hi Jeannot,

If I can do this easily in C#, I'm sure you can do this in VB.NET. (tested
using .NET 2.0, VS 2005)

1. Create a UserControl, call it UserControl1.cs : put your controls on it;
those controls whose attributes you wish to modify in derived classes : set
Modifiers property to 'Protected either in the Property Editor in Design
View or in the Designer.cs file via editing.

2. Add a new class to your project, call it DerivedClass1.cs. Add the
necessary Using statements that match those for UserControl1.

3. Set DerivedClass1 to inherit from UserControl1 : in C# :

public class DerivedClass1 : UserControl1

4. Define your constructor properly for the derived class : in C#

// note : in this case in C# use of : base() is not strictly
required, but if you define
// constructor overloads where you pass in parameters, you must make
sure the call to base()
// has a matching signature : see J. Liberty, Programming C# chapter
on Inheritance.
public DerivedClass1() : base() {}

I found it necessary to manually insert a call to InitializeComponent() into
the constructor after I had added NEW controls to the derived class and the
Design View finally "kicked in."

5. at this point you should be able to open the Design View of DerivedClass1
and edit the attributes of those controls in UserControl1 whose modifier
value you have set to 'Protected. I've noticed in VS 2005 that exactly when
the Design View for a derived UserForm appears is not predictable, but it
usually happens after a build or two. Of course you can then add new
controls to DerivedClass1, set the modifier property on its controls to
'Protected as desired if you are going to derive from that.

6. drawbacks :

a. if I now create a new class, follow the steps above, and derive it
from DerivedClass1 : those controls inherited from UserControl1 (which are
attribute editable in DerivedClass1) show up all right, they fire any event
handlers defined in UserControl1 just fine : but they appear locked in
Design View. I have been unable to get design view editing of control
attributes when there is more than one "level" of inheritance. Perhaps one
of our real "gurus" here can explain this or give a work-around for this.

7. caveats :

a. because you can do this doesn't mean you should do this : perhaps
sometimes copy and paste into new usercontrols is better ? or even copying
the usercontrol.cs file and re-naming it and adding it to the project and
then editing what you need to edit, and adding what you need to add ?

b. I give you 90/10 odds that J. Skeet, N. Paladino, H. Wagner, B.
Powell, P. Duniho, or one of our other "highly cherished" MVP's and
"masters" will chime in here with either a compelling argument why you
should not do this, or a compelling example of a better way to do this.

sic semper ad ignotus sapientae

best, Bill
 
Gentlemen, we have liftoff. I have to thank all of you because each
contribution helped.
And Bill, thanks for the time you put in your reply. I hit some road
blocks due to differences between C# and VB (or VS2005 & VS2008?)
And, let's not forget everyone who could written "you should not be
doing this", or "why don't you use Delphi instead", or "That's what
you get for using VB" who all deserve my warmest thanks.

This solution has been tested with VS2008 and .NET 3.5, in VB.

1- I created a UserControl called BaseControl. I added "Label1Base" on
its left side

2- I created another UserControl called DerivedControl. I added
"Label1Derived" on its right side

3- I closed Dev Studio, and loaded DerivedControl.designer.vb. I
changed its base class from System.Windows.Forms.UserControl to
BaseControl

4- Loaded Dev Studio, built everything.

I can now add children to the BaseControl, and the changes are
reflected in DerivedControl, and what I add to DerivedControl is
unique to it.


Note 1: After adding a child to your base control, it may not
immediately show in your derived class. In most cases you have to
rebuild, and then it appears.

Note 2: When adding a child to your derived control, make sure to not
give it a name that conflicts with a control in the base class. In
some cases DevStudio will let you do it, but then it'll stumble on a
flower in the carpet before long.

Note 3: In the base control, the default value for the child Modifier
is Friend, effectively preventing the derived control from relocating
it. If you want to be able to relocate the base control in the derived
control, you must set the child's Modifier to Protected or Protected
Friend.

Again, thanks to all. Any questions, I'll support this for the next
couple of days.
 
3- I closed Dev Studio, and loaded DerivedControl.designer.vb. I
changed its base class from System.Windows.Forms.UserControl to
BaseControl

Correction: The above sould say:
3- I closed Dev Studio, and loaded DerivedControl.designer.vb IN
NOTEPAD. I
changed its base class from System.Windows.Forms.UserControl to
BaseControl
 
Back
Top