Inheriting from a Form/Control

rbulph

Junior Contributor
Joined
Feb 17, 2003
Messages
397
I want to inherit from a form. When I try this I find that I can add controls to the inheriting class easily through use of the Toolbox and that class's designer, and all looks OK. The code for the new controls appears in an InitializeComponent method for the inheriting class. But when I want to create an instance of the inheriting class at run time, nothing that I have done to its designer is apparent. It seems that the InitializeComponent sub of the inheriting class is not happening. An example might make this clearer:

Code:
Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim f As New Class1
        f.Show()
    End Sub
End Class

Code:
Public Class Class1
    Inherits Form1

    Private Sub InitializeComponent()
        Me.CheckBox1 = New System.Windows.Forms.CheckBox
        Me.SuspendLayout()
        '
        'CheckBox1
        '
        Me.CheckBox1.AutoSize = True
        Me.CheckBox1.Location = New System.Drawing.Point(69, 173)
        Me.CheckBox1.Name = "CheckBox1"
        Me.CheckBox1.Size = New System.Drawing.Size(81, 17)
        Me.CheckBox1.TabIndex = 1
        Me.CheckBox1.Text = "CheckBox1"
        Me.CheckBox1.UseVisualStyleBackColor = True
        '
        'Class1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.ClientSize = New System.Drawing.Size(292, 273)
        Me.Controls.Add(Me.CheckBox1)
        Me.Name = "Class1"
        Me.Text = "C1"
        Me.Controls.SetChildIndex(Me.CheckBox1, 0)
        Me.ResumeLayout(False)
        Me.PerformLayout()

    End Sub

    Friend WithEvents CheckBox1 As System.Windows.Forms.CheckBox

End Class

Make sure that Form1 and Class1 are in different modules in the Explorer window so that the designer of each can be seen. If you look at Class1 in its designer you will see a checkbox and its title is "C1". But when you run the project it looks exactly like Form1.

So should I simply remove all the code from Class1's InitializeComponent method and put it into the Class1_Load event?
 
OK, if I create Class1 by adding a standard form to the project and having that inherit from Form1 rather than Form, everything works as expected. So by comparing the code in that form and in Class1 I can see that Class1 needs the following tag:

Code:
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
.

That fixes the problem.

Maybe Class1 also needs this code from the form, although I confess I don't know what it does:

Code:
 'Form overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing AndAlso components IsNot Nothing Then
            components.Dispose()
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer
 
Interestingly there is a case here where the autogenerated warning:

'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.

would not seem to be valid. If you have a container control in Form1 and want to add a control into it in Class1 then you cannot do this with the Windows Form Designer. It seems you're best doing this by adding code in the InitializeComponent sub of Class1.
 
Odd indeed. If you actually add the new form by selecting 'Inherited Form' from the list of items and picking the correct base class it seems to work fine though.
 
Hadn't noticed that you could add inherited forms and controls in this way, so thanks for pointing it out.
 
In C# the designer automatically inserts a call to InitializeComponent in the constructor, which goes in the user code rather than the designer code, so you notice right off the bat if it isn't there. I know that in VB the constructor is hidden in the designer code, so not only is it a pain to fix, but you probably won't even ever catch it. The designer is probably just not smart enough to insert the call to InitializeComponent unless you use PD's method. (The attribute you used probably clued the designer in and caused it to insert the call to InitializeComponent.)
 
Back
Top