From the June 2001 issue of MSDN Magazine.

MSDN Magazine

Using Inheritance in Windows Forms Applications
Ken Spencer
Download the code for this article:Basics0106.exe (194KB)
Browse the code for this article at Code Center:Inheritence in .NET

O

ne of the coolest features of Visual Basic.NET is inheritance, which provides the ability for one object to inherit another object's methods and properties. Not only does this save coding time initially, but it also saves time later on as changes in the parent object are reflected in all objects that inherit from it. Visual Basic.NET allows you to inherit classes and Windows® Forms. If you're familiar with object-oriented programming (OOP) concepts, then you know what inheritance is. For those of you who are not familiar with OOP, let's forget all the complicated stuff for a minute and just work with inheritance the easy way.
      The easiest way to get a handle on inheritance with Windows Forms is to look at an example. The sample application I'll present here simplifies a previously tedious task—namely, creating a consistent UI requiring clones of your interface elements. For instance, you may want your company logo in the top-left corner of each form and certain standard buttons in the upper-right corner of each form. To do this in Visual Basic® 6.0 and earlier, you can create a template and build each form from it, or you can create code that puts the logo and buttons on each form. Whichever approach you take, it will take time and effort to make it work the way you want.
      With Visual Basic.NET, this process is simple. You can build the form once, then each succeeding project can inherit from that form, acquiring its interface and its code automatically. If you change the master interface, each project inherits those changes. Windows Forms is the simplest and coolest use of form inheritance.
      The sample application is going to mock up part of the interface of an application. The master form will be frmMasterLayout.vb. Let's see what the prototype application I'm going to build looks like. Figure 1 shows two of the forms in the application. Notice how both forms have the same logo and logo placement, and the two buttons in the top-right corner are also the same. All of these features plus the About button on the Start form (on the rearmost form) are part of the master form, which is not shown in Figure 1. Instead of placing the image and buttons on each form, the forms simply inherit the functionality of the master form.

Figure 1 Inheritance from the Base Form
Figure 1Inheritance from the Base Form

      So, how can you try this at home? Well, this is where the fun begins because the process is relatively simple.

Creating the Base Form

      First, let�s create the master form. In Microsoft .NET parlance, this form is known as the base form because (as you may have guessed) it is the one that will serve as the base for the other forms. In other words, when you create a new form that inherits from the base form, the new form looks and acts just like it.
      To create the base form, start Visual Basic.NET. Select Create New Project from the Visual Studio® home page or from the File menu (if you have already started Visual Basic.NET). Click the Visual Basics Projects item in the left pane and select Windows Application in the right pane. Name this form MyProjBaseForm and click OK.
      To make this form a base form, you need to change the project type from Windows Application to a class library that your other forms can inherit from. To do this, right-click the project name and select Properties. Select Class Library from the Output type list (see Figure 2) on the General properties page and then click OK.
      Now you can add the master form and create its interface. First, delete the default form for the project. Next, right-click the project name in Solution Explorer, hover the mouse over Add, and select Add Windows Form from the shortcut menu. Name this form frmMasterLayout and click Open.
      Press F4 to open the form�s properties. Expand the Size property and set the width to 800 and the height to 600.
      Next, drag an Image control to the form. Open the properties for the image control and set the Image property to any image on your system. I used the 32X Tech logo. Set the Location X and Y properties to 8.
      Next, add a button control to the form and set its Name property to cmdClose and the Text property to Close. Set the Location X and Y properties to 704 and 8, respectively.
      Now you need to add two more buttons. Right-click the cmdClose button and select Copy. Right-click the form and select Paste. The new button will be pasted directly on top of the original button. Drag it to a location of 704 and 40, set its Name property to cmdStart, and set the Text property to Start. Change the Visible property to True.
      Now, copy the cmdStart button and paste it into the form.
      Move the new button to a location of 616 and 8. Set its Name property to cmdAbout and set the Text property to About. Now it�s time to change this button�s behavior. Change the Modifiers property to Protected, which will allow the properties of this control to be changed by any form that inherits the form the control is on. On the other two command buttons, this property is set to Private, effectively locking the property settings on these buttons. Also, make sure the Visible property of this button is False. This will turn off the button unless the inheriting form explicitly turns it on.
      To complete the buttons, double-click the Close button to open its Click event procedure. Add this code, which closes the form.

Me.Close()
By putting this in the base form, the code is created only once but reused many times.
      At this point, the master form is complete. Click the Save All button on the toolbar (Ctrl+Shift+S). Before you can inherit from the new master form, you must build (compile) the forms project. To build the project, you can press Ctrl+Shift+B or right-click the project name and select Build.
      If the build is successful, you should see the following message in the Output window:
Build: 1 succeeded, 0 failed, 0 skipped
If the build was not successful, you should see an error message in the Task window. Double-click the error message and the cursor should move to the line causing the error.

Inheriting from the Base Form

      Now that the base form project has been compiled, let�s use it in another project. From the File menu, select Add Project, then New Project. Click Visual Basic Projects in the left pane and select Windows Application in the right pane. Name this form MSDNWinFormsVI and click OK.
      Right-click the new project name and select Set as Startup Project. This sets this project to the running project when you use the F5 function key to start the application in debug mode.
      Before you use your base form, you need to create a reference to the library containing it. To create the reference, right-click the project name in Solution Explorer and select Add Reference. When the References dialog shows, click the Projects tab, and locate your base form library (MyProjBaseForm). Click the project name once as shown in Figure 3 to select it, then click Select, then click the OK button. Now your project has a reference to the base form library.
      Close the default form and delete it. Next, add a new WinForm by right-clicking the Project name in Solution Explorer and selecting Add Inherited Form. Change the forms name to frmStart and click Open.
      Now you should see your new form in the Design editor, as shown in Figure 4. Notice how the new form looks just like the base form. You can see how the Image control and the right two buttons are grayed out and can�t be selected. This is because those controls have their Modifiers property set to Private so they cannot be modified by a derived form.

Figure 4 The New Form Displayed in Design Editor
Figure 4The New Form Displayed in Design Editor

      Repeat the process of adding a new Inherited Windows form and name this form frmCustomerList. When this form opens in the Design editor, add a textbox control from the toolbox. Set its Multiline property to True and its Text property to "Customers go here". This textbox is simply a placeholder in the interfaces prototype for now. Save this form.
      Switch back to frmStart. Click the About button and change its Visible property to True. Next, add another button from the toolbox and name it cmdCustomerList. Set its Text property to Customer List and the Width (under the Size) to 136. Set the Locations X and Y properties to 144.
      Next, double-click cmdCustomerList and add the following code to the Click event:
Dim frmCustomerList As _
    MSDNMagWinFormsStep2UsingCode.frmCustomerList = _
    New MSDNMagWinFormsStep2UsingCode.frmCustomerList()
        
frmCustomerList.Show()
This code will display frmCustomerList when the button is clicked.
      Now press Ctrl+F5 to run the form. This starts the application without starting the debugger, which is usually a good bit faster than waiting for the debug process to start. You will probably notice the debug delay more on Web projects than Windows-based applications, since debugging a Web application is more intensive because it involves Microsoft Internet Information Services (IIS) and the .NET platform.
      At this point, frmStart should be running. You should see the About button also. Clicking the cmdCustomerList button should display the second form. The About button on the second form should not be displayed. You can close the second form by clicking Close. Clicking Close on the last form that�s running will stop the application, just as in Visual Basic 6.0 and earlier.

Where�s the Code?

      Where�s the inheritance code that makes all of this work? Let�s take a look at part of frmStart�s code.
      The first few lines import the namespaces used in the form. This is standard for most Windows Forms.
  Imports System.ComponentModel
  Imports System.Drawing
  Imports System.WinForms
      The following statement is used to create the Form class:
  Public Class frmStart
      The next line is the key to inheriting from the frmStart class:
  Inherits MSDNMagWinFormStep2Code.frmMasterLayout
The previous line replaces this one:
  Inherits System.WinForms.Form
which is used in a vanilla Windows Form to inherit from the Windows Forms class. Instead, the first statement derives your current form by inheriting from your base form.
      The rest of the code in the form is the same as a normal Windows Form. You can change a vanilla Windows Form to inherit from a base Windows Form by simply changing
Inherits System.WinForms.Form 
to the following:
Inherits MSDNMagWinFormStep2Code.frmMasterLayout
where the fully qualified name is the base form.
      Of course, there is more to inheritance than this one line of code. The reason inheritance works with Windows Forms is that Windows Forms are really classes. You can see this by the Class statement that defines the code for a Windows Form. Inheritance only works with classes, but since Windows Forms are classes, it works.
      When you created the reference to the base form library, Visual Studio.NET copied the library�s DLL into the BIN folder for your project. If you look at the properties for the reference, you will see the CopyLocal property is set to True. Looking at the file system, you can confirm that your project has a local copy of the DLL. If the base form has changes made to it, they will not be picked up by the derived classes until the local DLL is updated.
      You can use modifiers with the Class statement to control what can be done with a class. The MustInherit modifier specifies that the class cannot be created, it can only be inherited. This modifier would be useful for your base form.
      The NotInheritable modifier of the class statement specifies that the class cannot be inherited from. This modifier might be useful in the implementation class to stop developers from inheriting one or more of the forms.
      One reason to use the MustInherit and NotInheritable class modifiers is to control the implementation of your applications and classes. For instance, when you create a form, you probably don�t really plan for that form to be a basis for other forms. To prevent another developer from misusing your form, you can use NotInheritable to stop the inheritance.
      You should also be aware that since the visual inheritance of Windows Forms is still inheritance and based upon classes, other features of inheritance come into play. If you create methods and properties in base classes (either traditional classes or Windows Forms classes), you can control which methods and properties in the base class can be overridden by a derived class.
      The following excerpted code from the MSDN® Visual Basic Language Concepts demonstrates this nicely. The first class statement (Class1) creates a new class with two methods: Method1 and aMethod.
Class Class1
   Sub Method1()
      Messagebox.Show("This is a method in the base class.")
   End Sub
   Overridable Sub aMethod()
       Messagebox.Show("This is another method in the " _ &
       "base class.")
   End Sub
End Class
      The next class statement (Class2) creates another class. This class is inherited from Class1 and overrides the aMethod procedure by redefining it with the Overrides keyword:
Class Class2
   Inherits Class1
   Overrides Sub aMethod()
      Messagebox.Show("This is a method in a derived class.")
   End Sub
End Class
      This next code uses both classes. In this case Class1 can be used as a standard class, which it is. Class2 also behaves like a standard class, except that it does not define Method1 but still has a Method1 procedure. That is because Method1 is inherited from Class1:
Protected Sub TestInheritance()
   Dim C1 As New class1()
   Dim C2 As New class2()
   C1.Method1()
   C1.aMethod()
   C2.Method1()
   C2.aMethod()
End Sub
This code also demonstrates how the aMethod procedure lives in both Class1 and Class2. In this implementation, aMethod can be executed from both classes. If you wanted to make sure that only a derived class can supply aMethod, you can use MustInherit on the class statement for Class1.
      When a form inherits another form, it also inherits the methods and code of that form. From the Class1 and Class2 examples, you should see that controlling how a class is created and carefully planning the interface for the class are important for base forms as well as base classes.
      Another interesting thing about inheritance is the idea of the base class versus a derived class. What if you want to make sure that you execute code that is in the base class and not the current derived class? Then you can use the MyBase keyword to qualify a call to an underlying method in the base class. Using MyBase qualifies the reference to a method like prefixing the method with the name of the base class. You can also use the MyClass qualifier to execute a method in the current class. MyClass is useful to ensure that your method, not one in a derived class that overrides the method, is the one that will be executed.

Conclusion

      Inheritance requires a new way of thinking. There are those who feel that inheritance can be a bad thing. Inheritance is not bad; in fact, it is a great feature and one that developers have asked Microsoft for since Visual Basic 4.0 hit the streets. Just like classes or any other language feature, inheritance must be used properly to make it work for you.
      The mechanics of inheritance are pretty simple in .NET languages, especially in Visual Basic.NET. While there are a few more things you need to learn about flipping switches and compiling applications, the most important part is always the design. In fact, if you carefully design your application using inheritance, you�ll benefit from tools like Visio® or Visual Modeler. Proper prototyping and testing will also become increasingly important as your applications become more sophisticated.

Send questions and comments for Ken to basics@microsoft.com.
Ken Spencer works for the 32X Tech Corporation (https://www.32X.com), which produces a line of high-quality developer courseware. Ken also spends much of his time consulting or teaching private courses.