Adding a design time dialog and creating a VS project sample

See Also:
Article 1 in this series: Article 1 in a series about WinForms Wizards: The fastest Wizard in the West.
Article 2 in this series: A slightly better WinForms wizard, and slightly more work.
Article 3 in this series: Adding Named Panel Navigation to the WizardController
Article 4 in this series: Providing design time support for the Wizard Framework
Article 5 in this series: You're looking at it!

Abstract:
Once I actually started using the designer to create my wizards I realized that a designable wizard dialog would be really useful.  In fact, I was able to lay out two fairly decent wizard dialogs within a few minutes with the new designer base.  In addition I'm providing a somewhat complete dialog sample to get you started in designing your own wizards.  The new sample demonstrates using the designers for the dialogs, panels, skinning by changing the dialogs, and implementing the Main method.  The series is really close to being complete with this latest revision, and only a couple more enhancements need to be made before the framework can be used for any wizard project (or even entire applications).

TOC:

    1. Why is the designer support so helpful for the dialogs?
    2. Enabling designable dialogs through the DesignableWizardDialog class.
    3. A quick look at the sample dialog project and it's feature.
    4. Conclusion

1.  Why is the designer support so helpful for the dialogs?
Wizard dialogs can be relatively complex in terms of layout and design.  We've included two wizards in the sample project, and each has a relatively complex layout in terms of docking/flow layouts and nested container control structures.  To lay this out in code might take you a couple of hours in some cases, but the designer turns the entire operation into something that takes a few minutes.  This type of quick turn-around can make even the fastest of programmers much more productive (trust me, there are plenty of applications I haven't made because of not wanting to create the UI).

If you only have to design the dialog once, why does the time savings really matter?  After all, how often do you make a new wizard?  Well, I'm hoping that people use this for applications other than just straight up wizards.  It makes a lot of sense to implement any multiple form UI using a wizard type layout, even if it only has two forms to display.  Take the following examples:

  • Find/Search dialog with a results pane - A lot of people make this a single dialog that expands, but you could quickly implement this as a two panel wizard.
  • Web Service access dialogs - Often times you make web service calls in an application and have to custom code your own progress notification.  Using a wizard type layout to collect data, process the operation with a progress notification on a separate panel, then display the results on an end panel.  Once the data is retreived you can grab it off of the wizard framework and put it directly into your application.
  • Application configuration - Using a highly customized named navigation dialog you can provide an entire configuration framework.
  • Short utilities - Wizards don't have to be part of an application, hey can actually be the application.  Often times you go the full distance and create many different forms with lots of navigation and validation logic when a wizard might be more appropriate.

Design time support helps enable the wizard framework to quickly satisfy the needs of users trying to push out a new tool or application.  This has existed for quite some time on the ASP .NET platform with many users releasing wizard frameworks.  ASP .NET v2.0 will even include support for wizards natively.  Longhorn also has built in support for wizards and view navigation.  Windows Forms hasn't had any equivalent feature until now.

2.  Enabling designable dialogs through the DesignableWizardDialog class
Enough talk, time for some code.  We'll be going for a similar inheritance chain to that of the designable panels we created in the previous article.  In this case we need to store 4 protected Control fields.  These fields will map to the navigation buttons and UI root.  Normally inherited dialogs will just use these fields, but in the case they don't want to, we'll make all of the IWizardDialog properties inheritable so you can repoint them at the appropriate fields (I highly recommend you just use the protected fields and leave the properties as is). 

public class DesignableWizardDialog : Form, IWizardDialog {
    protected Control previousButton;
    protected Control nextButton;
    protected Control finishButton;
    protected Control uiRoot;
   
    public DesignableWizardDialog() { }
   
    [Browsable(false)] public virtual Control NavigatePrevious  { get { return previousButton; } }
    [Browsable(false)] public virtual Control NavigateNext      { get { return nextButton; } }
    [Browsable(false)] public virtual Control NavigateFinish    { get { return finishButton; } }
    [Browsable(false)] public virtual Control UIRoot            { get { return uiRoot; } }
    [Browsable(false)] public virtual bool Display              { get { return this.Visible; } set { this.Visible = value; } }
}

Then we have to enable the designable control setting features.  You see, if you have controls on your form, and designable properties of type Control, the VS designer will enable you to select from all controls you've added to the form and let you set the properties to them.  I think this is pretty darn cool because I can drop three buttons on the form then set the properties to point to them, add a panel and point the UI root at that, and I'm done.  I can competely design the wizard dialog now without any code at all.

[Browsable(true)]
[Category("Wizard")]
[Description("Set the control used for previous panel navigation")]
public virtual Control NavigatePreviousControl { get { return this.previousButton; } set { this.previousButton = value; } }

[Browsable(true)]
[Category("Wizard")]
[Description("Set the control used for next panel navigation")]
public virtual Control NavigateNextControl { get { return this.nextButton; } set { this.nextButton = value; } }

[Browsable(true)]
[Category("Wizard")]
[Description("Set the control used for finishing the wizard")]
public virtual Control NavigateFinishControl { get { return this.finishButton; } set { this.finishButton = value; } }

[Browsable(true)]
[Category("Wizard")]
[Description("Sets the control where all panels will be displayed")]
public virtual Control UIRootControl { get { return this.uiRoot; } set { this.uiRoot = value; } }

3.  A quick look at the sample dialog project and it's features
I think a sample project would definitely help get people used to the wizard framework.  I'm creating a basic wizard project with two dialogs that each share 3 wizard panels.  You can use the project to check out the framework, implement your own wizards, and see how cool the skinnability feature is.  Here is a basic file layout for the project.

The dialogs are also pretty neat to look at.  Here is the cooler of the two dialogs and one of the panels.

Running the sample, you'll get a chance to run through the wizard twice.  The first time you'll use the simple dialog (not shown), and the second time through you'll use the upgraded cooler dialog.  This just shows you how easy it is to change your user interface, allow skinning within your application, or any number of other features.  The WizardController will make sure the new dialog supports all of the interfaces and has all of the controls to make the wizard actually work.

4.  Conclusion
I keep wanting to make some cool wizards to show off using the framework, and each time I think of a cool new feature that would make things that much easier.  Dungeon Dialogs is coming along and is already quite cool, but I'm going to hold it off until the Metadata support is in place.  The Metadata support will allow each dialog to communicate variables and hence each dialog will have access to your character information as you navigate the dungeon using a wizard.  I think this will be a cool sample to say the least.

Downloadable Project (C#):  WizardControllerArticle5.zip on Games4Dotnet.com
Full Source (C#): Code-Only: Winforms Wizard Series Article 5 (C#)
Full Source (VB .NET): Code-Only: Winforms Wizard Series Article 5 (VB .NET)
Full Source (JScript .NET): Code-Only: Winforms Wizard Series Article 5 (JScript .NET)
Full Source (Managed C++): Code-Only: Winforms Wizard Series Article 5 (Managed C++)

Published Wednesday, April 21, 2004 5:55 PM by Justin Rogers
Filed under:

Comments

Thursday, April 22, 2004 2:39 AM by tracdalat

# re: Adding a design time dialog and creating a VS project sample

hey, I've follow these articles from the beginning. Thanks a lot, it's very helpful; and great (of course)
Sunday, June 13, 2004 4:00 PM by David

# Capturing panel events

Hi.
I'm really impressed with your work.
But I can't figure out how each panel can control the various events. For exemple, your license panel should be able to control if the license has been accepted or not, and change the nextPanel accordingly.
Another problem is how each panel can control the form it belongs to. For exemple, to change the "Wizard Step Title" text.

Thanks. David
Sunday, June 13, 2004 7:34 PM by Justin Rogers

# re: Adding a design time dialog and creating a VS project sample

David, you'd have to look at Article 6 that covers the metadata API and container. I haven't found the time to push out Article 7, which actually implements the metadata API into the wizard itself and allows for the features of controlling Next/Previous enable/disable, as well as changing the Wizard Title etc...
Thursday, July 03, 2008 9:16 AM by j.monty

# re: Adding a design time dialog and creating a VS project sample

curious - is this code public domain for anyone to use in anything, as long as you get the Copyright?

Sunday, July 12, 2009 9:49 PM by Sheryl

# re: Adding a design time dialog and creating a VS project sample

Hi,

   I had been following with the article. This is good but too bad I'm not able to see the images on item (3.  A quick look at the sample dialog project and it's features). Anyway, to see it?

Leave a Comment

(required) 
(required) 
(optional)
(required)