A Reusable Wizard Component

CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Environment: .NET, C#, VS.NET, Win2K

Introduction

A few months back, I was given the task of porting an MFC application to .NET using C#. It surprised me to find no direct support for wizard dialogs in .NET. There were property pages in the form of the unwieldy TabControl class, but no dual functionality as I had come to expect from CPropertySheet and CPropertyPage. I think it was an even bigger surprise when I did a search for wizard dialogs implemented in .NET and came up empty. Am I the only one still using wizards? Is there some really easy way to do it in .NET that I completely overlooked? Whatever the answer, I resigned myself to write a reusable wizard component in .NET that mimicked, as closely as possible, the MFC implementation.

My goals for this project were the following:

  1. Be able to create wizards programatically in a manner similar to what I had become accustomed to using MFC, and
  2. Be able to use the Windows Form Designer to create individual wizard pages in a manner similar to how I was able to create them by using the dialog editor.

This article presents two classes that enable you to create wizards in .NET in much the same way they are created using MFC. Two additional classes make it easy to implement Wizard 97-style wizards, as well.

The Classes

The first two classes to be discussed, WizardForm and WizardPage, are meant to correspond to CPropertySheet and CPropertyPage, respectively. The remaining two classes, ExternalWizardPage and InternalWizardPage, are merely helper classes to assist in building Wizard 97-style wizards.

WizardForm

WizardForm is derived from Form and provides the basic mechanisms for managing a collection of WizardPage instances. Additionally, it provides default the functionality and UI layout for the Back, Next, Finish, and Cancel buttons. The wizard-related methods of CPropertySheet, such as SetWizardButtons, are implemented, as well. A brief summary of each method this class introduces is presented below.

    public void SetFinishText( string )

    Sets the text for the Finish button.

    public void SetWizardButtons( WizardButtons )

    Enables or disables the Back, Next, and Finish buttons in the wizard.

The first thing to do when creating your own wizard is to extend this class, typically by using the Add Inherited Form command within VS.NET. You may edit the properties of the inherited controls and add additional controls beyond the standard wizard buttons if you want.

WizardPage

WizardPage is derived from UserControl. The wizard-related methods of CPropertyPage, such as OnSetActive, OnWizardNext, and so forth, are implemented. A brief summary of each property/method this class introduces is presented below.

    protected WizardForm Wizard { get; }

    Gets the WizardForm to which this WizardPage belongs.

    protected internal virtual bool OnKillActive()

    Called when this page is no longer the active page. Do data validation tasks here.

    protected internal virtual bool OnSetActive()

    Called when this page becomes the active page.

    protected internal virtual string OnWizardBack()

    Called when the Back button is clicked. Return WizardForm.DefaultPage to advance to the previous page, WizardForm.NoPageChange to prevent the page from changing, or the value of the Name property of the page to be displayed.

    protected internal virtual string OnWizardNext()

    Called when the Next button is clicked. Return WizardForm.DefaultPage to advance to the next page, WizardForm.NoPageChange to prevent the page from changing, or the value of the Name property of the page to be displayed.

    protected internal virtual bool OnWizardFinish()

    Called when the Finish button is clicked. Return true to close the wizard or false to prevent the wizard from closing.

Once your custom WizardForm is complete, you create one or more WizardPage-derived classes. You create your own page by extending this class, or any class derived from it, typically using the Add Inherited Control command within VS.NET. Add whatever combination of controls you would like to be displayed on this page. To associate the page with its wizard, you add it to the Controls collection of the appropriate WizardForm.

ExternalWizardPage

ExternalWizardPage extends WizardPage and represents an external (for example, the first or last) page in a Wizard 97-style wizard. It merely provides the required controls with the proper positioning and properties to satisfy the Wizard 97 specifications.

InternalWizardPage

InternalWizardPage extends WizardPage and represents an internal (for example, neither the first nor last) page in a Wizard 97-style wizard. Again, it merely provides the required controls with the proper positioning and properties to satisfy the Wizard 97 requirements.

Using WizardForm and WizardPage in Your Application

Any time you want to add a WizardPage-derived class to your project, use the Add Inherited Control command. Select WizardPage (or any other WizardPage-derived class, such as ExternalWizardPage or InternalWizardPage) as the component to inherit from, and add controls to the page as desired.

To add the wizard itself to your project, use the Add Inherited Form command. Select WizardForm (or any other WizardForm-derived class) as the component to inherit from. You may add additional controls and behavior if you want. The wizard pages can be added to the form in the constructor, for example,

  public MyWizardForm()
  {
      // Some initialization code here
      //     .
      //     .
      //     .

      Controls.AddRange( new Control[] {
          new MyFirstWizardPage(),
          new MySecondWizardPage(),
          new MyThirdWizardPage()
      } );
  }

Note that you can directly use the WizardForm and WizardPage classes without deriving your own classes, but in most cases it’s a very inelegant solution.

Summary

This article has described a set of two reusable classes for implementing wizards within the .NET environment. Two additional classes are provided to assist in implementing wizards that must conform to the Wizard 97 specification.

There are bound to be some areas I’ve overlooked in this implementation. For instance, I have not tested these classes when the WizardForm is acting as the main window of an application (for example, it was passed as the Form argument to Application.Run). Also, the code is not localized. However, the source code should serve as a good starting point for developing your own, possibly more robust, .NET wizard implementations.

Downloads


Download source and demo project (unified solution) – 64 KB

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read