When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article
Jobs

ASP ASP.NET ASP FAQs Message Board Feedback ASP Jobs
 
Print this Page!
Published: Wednesday, June 14, 2006

Creating a Step-by-Step User Interface with the ASP.NET 2.0 Wizard Control: The Basics

By Scott Mitchell


Introduction


The wizard - a standard user interface element in desktop applications - takes the user through a series of discrete steps in order to accomplish some task. A wizard step typically includes instructions, input controls, and an interface for moving between the wizard's steps (typically Next and Previous buttons, with a Finish button at the last step). Furthermore, wizards often include different steps depending on the inputs chosen in previous steps.

Wizards have typically been the domain of desktop applications, but have recently become more prevalent in web applications. In ASP.NET 1.x, developers who wanted to implement a wizard-like user interface would often use multiple Panel Web controls, one for each Wizard step. As they user progressed through the wizard by hitting the Next and Previous buttons, the appropriate Panel could be displayed (have its Visible property set to True), while the others hidden (have their Visible properties set to False).

ASP.NET 2.0 makes creating wizard interfaces a lot less work thanks to its new Wizard control. With the Wizard control, we can define a series of Wizard steps and specify the content - static HTML and Web controls - that belongs in each step along with the function of the step, whether it's the first step, one step in the series of steps, the final step, or a summary step to appear after the wizard has completed. The Wizard control automatically includes the appropriate navigation elements for each step, remembers the values entered into the Web controls in each step, and includes a rich event model from which programmatic logic can be added to perform the desired task upon finishing the wizard (among other tasks).

In this article we'll see how to use the wizard control to break up the steps involved in inserting a record into a database, although the concepts can be extended to any multi-step task. We'll focus on the basics in this article; refer to Creating a Step-by-Step User Interface with the ASP.NET 2.0 Wizard Control: Improving and Customizing the User Experience for more advanced features of the Wizard control. Read on to learn more!

- continued -

Specifying the Wizard Control's Steps


The Wizard control is useful for breaking down a complex task into a sequence of simpler steps. Each step in the Wizard control can include the following information:
  • A Title - along with each step, the Wizard control can optionally include a side bar that lists the available steps in the wizard and allows the user to quickly jump from one step to another. The title, if provided, is what appears in the side bar for the step.
  • A StepType - the navigation controls displayed in each step depend upon the value of the step's StepType property. This property can be assigned one of the following values:
    • Start - the Start step includes just a Next button
    • Step - Step steps include both a Next and Previous button
    • Finish - the Finish step includes Next, Previous, and Finish buttons
    • Complete - the Complete step, if provided, displays a summary of the task performed after the Finish button has been clicked from the Finish step.
    • Auto - (the default) the navigation controls rendered are automatically determined based on the index of the step itself. That is, the first step in the wizard is assumed to be the Start step, the last step the Finish step, and all other steps are considered Step steps; no step is automatically considered a Complete step (if you want a Complete step, it must be explicitly specified).
  • Content - each step can be composed of static HTML and Web controls. Often, steps will include Web controls for collecting user input, which is then used to perform the desired task after the Finish button has been clicked.
When you add a Wizard to an ASP.NET page you can specify the steps through the Designer or directly through the declarative syntax. From the Designer, click on the Wizard control, then go to the Properties window and scroll down to the WizardSteps property. Clicking on that property will bring up the WizardStep Collection Editor, from which you can add or remove steps, reorder them, and alter their properties.

To add content to a step, select the step from the Wizard's smart tag and then simply type in the text or add the Web controls from the Toolbox that you want to appear in the step.

The steps can also be examined and modified through the declarative syntax. The Wizard control specifies its steps through the <WizardSteps> element, with each step implemented as an <asp:WizardStep> or <asp:TemplatedWizardStep>. The Title and StepType properties can be specified through attributes in the <asp:WizardStep> or <asp:TemplatedWizardStep> tags; the actual content for the step is placed within the tags.

<asp:Wizard ID="AddEmployeeWizard" runat="server" CellPadding="5" Width="95%">
   <WizardSteps>
      <asp:WizardStep runat="server" Title="Step 1" StepType="Start">
         ... Content for Step ...
      </asp:WizardStep>
      <asp:WizardStep runat="server" Title="Step 2" StepType="Step">
         ... Content for Step ...
      </asp:WizardStep>
      ...
      <asp:WizardStep runat="server" Title="Step 3" StepType="Finish">
         ... Content for Step ...
      </asp:WizardStep>
   </WizardSteps>
</asp:Wizard>

Creating a Wizard for Inserting a New Record


To illustrate how to use the Wizard control, I've whipped up a demo (which can be downloaded from the end of this article) that provides a wizard for collecting information that is, at wizard's completion, inserted into a database. In particular, this demo inserts data into an Access database that has an Employees table; this table has the following schema:

Employees
ColumnData TypeComments
EmployeeIDAutoNumberPrimary Key / Auto-Increment ID value
FirstNameTextRequired
LastNameTextRequired
SalaryCurrencyRequired
HireDateDate/TimeRequired
PhoneTextOptional
StreetTextOptional
CityTextOptional
EmailTextOptional

Rather than having one screen that prompts the user for all of these inputs at once, let's instead have a Wizard control where each step asks for a subset of the input values. The following screen shots illustrate this goal:

To create such an interface we need a wizard with at least three steps (one for the name information, one for salary and hire date, and one for the contact information). In addition to these three steps, let's also add an "Introduction" step that includes instructions. In the "Introduction" step, I have just text (and HTML) explaining the task about to be performed. In the other three steps, I include Web controls for collecting user input - a Calendar control for the HireDate field and TextBoxes for the other seven fields.

Let's look at the declarative syntax for this Wizard control. Since it's rather lengthy, let's first just focus on the overall structure and then dive into each step's content:

<asp:Wizard ID="AddEmployeeWizard" runat="server" Width="95%">
    <WizardSteps>
        <asp:WizardStep runat="server" Title="Introduction">
            ...
        </asp:WizardStep>
        <asp:WizardStep runat="server" Title="Name">
            ...
        </asp:WizardStep>
        <asp:WizardStep runat="server" Title="Salary & Hire Date">
           ...
        </asp:WizardStep>
        <asp:WizardStep runat="server" Title="Contact Information">
           ...
        </asp:WizardStep>
    </WizardSteps>
</asp:Wizard>

I've omitted virtually all style-related markup for brevity. However, I did leave in the Width="95%" setting in the <asp:Wizard> tag. If you don't set the Width for the entire Wizard control each step's width will be adjusted based on the content in the step. Therefore, you may want to set the Width of the Wizard control to some explicit value, either in pixels or as a percentage of the screen width; similarly, you may want to also set the Height property, if you also want a fixed height.

Note that for each <asp:WizardStep> I've omitted the StepType property. If you omit this property, the StepType is determined by the ordinal index of the step. Therefore, the "Introduction" step is made a Start step, the "Contact Information" step a Finished step, and the "Name" and "Salary & Hire Date" steps are made Step steps.

Let's look at the "Name" step's content. Here, I've added two TextBoxes (and an HTML <table> for positioning purposes) to collect the new employee's FirstName and LastName values.

<asp:WizardStep runat="server" Title="Name">
    <h3>Employee Name Information</h3>
    <table border="0">
        <tr>
            <td class="InputLabel">First Name:</td>
            <td class="InputControl">
                <asp:TextBox ID="FirstName" runat="server" />
            </td>
        </tr>
        <tr>
            <td class="InputLabel">Last Name:</td>
            <td class="InputControl">
                <asp:TextBox ID="LastName" runat="server"  />
            </td>
        </tr>
    </table>
</asp:WizardStep>

The other steps include the appropriate markup and Web control syntax to collect the needed input. Note that for each step we do not need to specify the navigation controls. The appropriate Start, Next, Previous, and Finish buttons are automatically added based on the step's StepType setting.

Accessing the Content Defined in a Wizard Step


Eventually, after the Finish button has been clicked, we'll need to process the user's input and perform the desired task (in this case, inserting a record into the Employees table). At this point - or perhaps earlier in the Wizard life cycle - we may want to programmatically access the values entered by the user into the user controls. This can be accomplished by referencing the control's directly via their ID values in the code behind class, just like you would had the controls been defined outside of the Wizard control.

In order to insert a record when the Finished button is clicked, we'll need to do one of two things:

  • Write ADO.NET code that connects to the database and issues the appropriate INSERT statement, passing in the values entered by the user in the Web controls
  • Add an AccessDataSource or SqlDataSource control to the page and specify its InsertCommand property. We can then use a series of <asp:ControlParameter> values in the InsertParameters collection to read the values entered by the user and use those values in the actual INSERT statement. With this approach the only code we have to write is one line - we must invoke the data source control's Insert() method once the Finish button is clicked.
Let's use the second option (see the Accessing and Updating Data in ASP.NET 2.0 article series for more information on working with data source controls). The one subtlety here is that the <asp:ControlParameter> cannot see the controls in the <asp:WizardStep> unless it's placed within one of the <asp:WizardStep>s. I've put this control in the final step, along with the markup and Web controls for collecting the user's contact information:

<asp:WizardStep runat="server" Title="Contact Information">
    <h3>Employee Contact Information</h3>
    <table border="0">
        <tr>
            <td class="InputLabel">Street:</td>
            <td class="InputControl">
                <asp:TextBox ID="Street" runat="server" MaxLength="100" Columns="25"></asp:TextBox>
            </td>
        </tr>
        <tr>
            <td class="InputLabel">City:</td>
            <td class="InputControl">
                <asp:TextBox ID="City" runat="server" MaxLength="25" Columns="15"></asp:TextBox>
            </td>
        </tr>
        <tr>
            <td class="InputLabel">Phone:</td>
            <td class="InputControl">
                <asp:TextBox ID="Phone" runat="server" MaxLength="25" Columns="12"></asp:TextBox>
            </td>
        </tr>
        <tr>
            <td class="InputLabel">Email:</td>
            <td class="InputControl">
                <asp:TextBox ID="Email" runat="server" MaxLength="100" Columns="25"></asp:TextBox>
            </td>
        </tr>
    </table>


    <asp:AccessDataSource ID="InsertEmployeeDataSource" runat="server" DataFile="~/App_Data/Employees.mdb"
        InsertCommand="INSERT INTO [Employees] ([FirstName], [LastName], [Salary], [HireDate], [Phone], [Street], [City], [Email]) VALUES (?, ?, ?, ?, ?, ?, ?, ?)">
        <InsertParameters>
            <asp:ControlParameter Name="FirstName" Type="String" ControlID="FirstName" PropertyName="Text" />
            <asp:ControlParameter Name="LastName" Type="String" ControlID="LastName" PropertyName="Text" />
            <asp:ControlParameter Name="Salary" Type="Decimal" ControlID="Salary" PropertyName="Text" />
            <asp:ControlParameter Name="HireDate" Type="DateTime" ControlID="HireDate" PropertyName="SelectedDate" />
            <asp:ControlParameter Name="Phone" Type="String" ControlID="Phone" PropertyName="Text" />
            <asp:ControlParameter Name="Street" Type="String" ControlID="Street" PropertyName="Text" />
            <asp:ControlParameter Name="City" Type="String" ControlID="City" PropertyName="Text" />
            <asp:ControlParameter Name="Email" Type="String" ControlID="Email" PropertyName="Text" />
        </InsertParameters>
    </asp:AccessDataSource>

</asp:WizardStep>

The Wizard Control Event Model


When the user moves from one wizard step to another, the Wizard control raises one or more events. The ActiveStepChanged event fires anytime one step is about to transition to another. The NextButtonClick and PreviousButtonClick events fire when the user clicks the Next or Previous button, respectively. The FinishButtonClick event is raised when the Finish button is clicked. In this demo we'll only examine one of these events, FinishButtonClick. We'll create an event handler for this event to insert the employee record. The other events are useful for performing server-side validation of user input or implementing a non-linear workflow (for example, if, after clicking Next, the Next step depends on the user's input in this step or a previous one).

The event handler for the FinishButtonClick event for our demo is painfully simply - we just need to invoke the AccessDataSource control's Insert() method. At that point, the AccessDataSource control will grab the values from the specified controls and issue the INSERT statement. After inserting the data, the event handler redirects the user back to the site's homepage.

'This event handler fires when the user clicks Finish. We need to insert the new employee record into the database
Protected Sub AddEmployeeWizard_FinishButtonClick(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.WizardNavigationEventArgs) Handles AddEmployeeWizard.FinishButtonClick
    'Insert the employee into the database
    InsertEmployeeDataSource.Insert()

    'Send the user back to the homepage
    Response.Redirect("~/Default.aspx")
End Sub

In addition to this event handler, our page also includes a Page_Load event handler that sets the HireDate Calendar control's SelectedDate property to the current date on the first page load. (You can omit this if you don't want to Calendar to be set to the current date, by default.)

Limitations of Our Demo


Our demo has some limitations. First off, there's no input field validation. While the FirstName field is a required field in the database, the user may omit this value, leading to an OleDb-level exception upon attempting to insert the employee record. This can be remedied using standard ASP.NET validation controls, which will prevent the user from moving to any other step than the previous one if the validation controls do not report the data as being valid. Also, any additional server-side validation checks can be performed by creating an event handler for the NextButtonClick event.

Another annoyance is that when moving from one step to another, we have to continuously click in the input field to start entering data. Ideally, moving to the next screen would automatically place the keyboard's focus in the first input control on the page. Moreover, you may notice that after entering data into the TextBoxes and hitting Enter, the wizard goes to the previous step. This is because the Previous button appears before the Next button.

In Creating a Step-by-Step User Interface with the ASP.NET 2.0 Wizard Control: Improving and Customizing the User Experience we'll see how to overcome these shortcomings. We'll also see how to add a Complete step to the Wizard control that shows a summary of the action performed. Additionally, we'll see how to use the <asp:TemplatedWizardStep> control, which allows us to customize the navigation controls for a particular step, as well as how to implement custom and non-linear progression through the Wizard's steps. (Demos that accomplish these goals are available in the download at the end of this article.)

Conclusion


Often, it helps to break a complex step into a series of simpler ones. This is the premise behind the wizard, a standard user interface element that consists of a series of steps and Next, Previous, and Finish buttons that allow the user to progress through these steps toward accomplishing some larger goal. In an ASP.NET application we can create such a user interface using the Wizard control.

As we saw in this article, the Wizard control is made up of a number of discrete steps that include the step's title, its StepType, and content. The StepType property dictates the type of navigation controls the step possesses; the content for the step includes text and Web controls for processing that step. The Web controls defined within the wizard's steps can be accessed programmatically like any other control on the page from the ASP.NET page's code-behind class, and are commonly accessed from the event handler for the Wizard control's FinishButtonClick event.

This article touched on the basics of the Wizard control. For a look at more advanced Wizard-related topics, check out: Creating a Step-by-Step User Interface with the ASP.NET 2.0 Wizard Control: Improving and Customizing the User Experience.

Happy Programming!

  • By Scott Mitchell


    Attachments


  • Download the code used in this article

    Suggested Readings


  • Several Wizard control examples
  • The ASP.NET 2.0 Wizard Control
  • Summary of the ASP.NET 2.0 Wizard Control
  • Working with the Wizard Control in ASP.NET 2.0
  • Creating a Step-by-Step User Interface with the ASP.NET 2.0 Wizard Control: Improving and Customizing the User Experience


  • ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article