You want to create a form that appears, from the user’s perspective, to consist of multiple pages, while keeping all of your code in one .aspx file and the code-behind that accompanies it.
Create one ASP.NET page. Use a Wizard
control with a WizardStep
control containing the HTML for each of the “virtual” pages you wish to display. The output of a typical multipage form is shown in Figures 4-1, 4-2, 4-3, 4-4 through 4-5. Examples 4-10, 4-11 through 4-12 showthe .aspx and code-behind files for an application that implements this solution.
In classic ASP, a series of questions or prompts, such as those on a survey or wizard, is typically implemented using multiple ASP pages with each submitting to the next in turn. Because ASP.NET 2.0 allows you to submit a form to another page, this same approach can still be used; however, ASP.NET 2.0 provides a simpler approach using the Wizard
control.
The Wizard
control provides the infrastructure you need to present a series of virtual pages to the user including the requisite navigation controls for moving forward and backward in the series. The virtual pages are defined using a WizardStep
control for each of the individual pages you want to present to the user. By defining the step type for the WizardStep
controls (Start, Step, Finish, Complete
, and Auto
), the Wizard
control will display the appropriate navigation buttons. The navigation buttons displayed for each step type are shown below.
Table 4-1.
WizardStep type |
Navigation buttons displayed |
---|---|
Start |
Next |
Step |
Previous, Next |
Finish |
Previous, Complete |
Complete |
None |
Auto |
Automatically generates the navigation buttons as required by the position of the |
The example solution we present here uses the Wizard
control and a series of WizardStep
controls to display a series of questions in a short survey.
Tip
Refer to Recipe 4.2 if you are determined to stick to the multiple form approach.
In our example, the .aspx file contains one Wizard
control and five WizardStep
controls. The first WizardStep
contains the first question (“Do you currently use ASP.NET 1.x?”) along with a RadioButtonList
control for the response. The second WizardStep
control contains the second question (“How long have you been using ASP.NET 1.x?”) along with a DropDownList
control for the response. The third and fourth WizardStep
controls are the same as the first and second steps with questions related to ASP.NET 2.0. The fifth WizardStep
control contains a message thanking the user for taking the survey.
The Page_Load
event handler in the code-behind initializes two arrays containing the possible answers to the questions and binds the data to the RadioButtonList
and DropDownList
controls in steps 1 through 4, as shown in Examples 4-11 (VB) and 4-12 (C#). We used this approach to reuse the data and to set the stage for potentially populating the available responses from a database.
We have implemented event handlers in the code-behind for the wizard’s next and previous button click events to demonstrate the ability to skip questions as a function of the user’s responses. In the event handler for the next button click event (wzSurvey_NextButtonClick
), we check to see if the current step is for one of the “use” questions. If the user responds by indicating she has not used ASP.NET, there is no point in asking how long she has used the product, so we skip the next step using the wizard’s MoveTo
method.
'skip steps as a function of the users answers Select Case e.CurrentStepIndex Case 0 If ((rbStep1.SelectedIndex >= 0) AndAlso _ (rbStep1.SelectedItem.Text.Equals("No"))) Then 'user does not use ASP.NET 1.x so move to 2.0 questionwzSurvey.MoveTo(step3)
End If Case 2 If ((rbStep1.SelectedIndex >= 0) AndAlso _ (rbStep3.SelectedItem.Text.Equals("No"))) Then 'user does not use ASP.NET 2.0 so move to complete stepwzSurvey.MoveTo(step5)
End If Case Else 'nothing required End Select // skip steps as a function of the users answers switch (e.CurrentStepIndex) { case 0: if ((rbStep1.SelectedIndex >= 0) && (rbStep1.SelectedItem.Text.Equals("No"))) { // user does not use ASP.NET 1.x so move to 2.0 questionwzSurvey.MoveTo(step3);
} break; case 2: if ((rbStep1.SelectedIndex >= 0) && (rbStep3.SelectedItem.Text.Equals("No"))) { // user does not use ASP.NET 2.0 so move to complete stepwzSurvey.MoveTo(step5);
} break; default: // nothing required break; }
In the wizard’s previous button click event handler (wzSurvey_PreviousButtonClick
), we do the same checks, but this time for the user navigating in the reverse direction.
When the final step is reached, the survey should be saved in your data store. We do this in the event handler for the ActiveStepChanged
event by checking to see if the ActiveStepIndex
is equal to the last step in the series.
'check to see if the complete step is the active stepIf (wzSurvey.ActiveStepIndex = wzSurvey.WizardSteps.Count - 1) Then
'survey is complete so production application should store the data 'in an applicable data store End If // check to see if the complete step is the active stepif (wzSurvey.ActiveStepIndex == wzSurvey.WizardSteps.Count - 1)
{ // survey is complete so production application should store the data // in an applicable data store }
Warning
The Wizard
control has a Finish
button click event that can be used to trigger your code to save the results; however, if your implementation of the Wizard
control (like our example) allows the user to skip steps, it is possible the Finish step will never be displayed and the Finish
button click event will not occur.
In addition to sequential navigation, the Wizard
control provides the ability to perform direct navigation through the series of steps by displaying a sidebar with links to each step, as shown in Figure 4-6. The sidebar is enabled by setting the DisplaySideBar
attribute of the Wizard
control to true.
<asp:Wizard ID="wzSurvey" runat="server"
CssClass="wizardBody" Width="75%" align="center"
HeaderText="ASP.NET Usage Survey"
HeaderStyle-CssClass="wizardHeader"
StepStyle-HorizontalAlign="Left"
StepStyle-VerticalAlign="Middle"
DisplaySideBar="true"
SideBarStyle-CssClass="wizardSideBar"
OnNextButtonClick="wzSurvey_NextButtonClick"
OnPreviousButtonClick="wzSurvey_PreviousButtonClick"
OnActiveStepChanged="wzSurvey_ActiveStepChanged" >
By using the style attributes for each of the sections of the Wizard
control, almost everything about the Wizard
control can be configured to match the look and feel of your application.
Example 4-10. Simulating a multipage form (.aspx)
<%@ Page Language="VB" MasterPageFile="~/ASPNetCookbookVB.master"
AutoEventWireup="false"
CodeFile="CH04SurveyDataVB1.aspx.vb"
Inherits="ASPNetCookbook.VBExamples.CH04SurveyDataVB1"
Title="Using the Wizard Control For Data Collection" %>
<asp:Content ID="pageBody" Runat="server" ContentPlaceHolderID="PageBody">
<div align="center" class="pageHeading">
Using the Wizard Control For Data Collection (VB)
</div>
<asp:Wizard ID="wzSurvey" runat="server"
CssClass="wizardBody" Width="75%" align="center"
HeaderText="ASP.NET Usage Survey"
HeaderStyle-CssClass="wizardHeader"
StepStyle-HorizontalAlign="Left"
StepStyle-VerticalAlign="Middle"
DisplaySideBar="false"
OnNextButtonClick="wzSurvey_NextButtonClick"
OnPreviousButtonClick="wzSurvey_PreviousButtonClick"
OnActiveStepChanged="wzSurvey_ActiveStepChanged" >
<WizardSteps>
<asp:WizardStep ID="step1" runat="server"
StepType="Start" Title="1.x Use">
<asp:Label ID="lbl1" runat="server"
CssClass="wizardStep"
Text="Do you currently use ASP.NET 1.x?" />
<asp:RadioButtonList ID="rbStep1" Runat="server"
RepeatLayout="Flow"
RepeatDirection="Horizontal"
CssClass="wizardStep" />
</asp:WizardStep>
<asp:WizardStep ID="step2" runat="server"
StepType="Step" Title="1.x Experience">
<asp:Label ID="lbl2" runat="server"
CssClass="wizardStep"
Text="How long have you been using ASP.NET 1.x?" />
<asp:DropDownList ID="ddStep2" runat="server"
CssClass="wizardStep" />
</asp:WizardStep>
<asp:WizardStep ID="step3" runat="server"
StepType="Step" Title="2.0 Use">
<asp:Label ID="lbl3" runat="server"
CssClass="wizardStep"
Text="Do you currently use ASP.NET 2.0?" />
<asp:RadioButtonList ID="rbStep3" Runat="server"
RepeatLayout="Flow"
RepeatDirection="Horizontal"
CssClass="wizardStep" />
</asp:WizardStep>
<asp:WizardStep ID="step4" runat="server"
StepType="Finish" Title="2.0 Experience">
<asp:Label ID="lbl4" runat="server"
CssClass="wizardStep"
Text="How long have you been using ASP.NET 2.0?" />
<asp:DropDownList ID="ddStep4" runat="server"
CssClass="wizardStep" />
</asp:WizardStep>
<asp:WizardStep ID="step5" runat="server"
Ste1pType="Complete"
Title="Complete" >
<asp:Label ID="lbl5" runat="server"
CssClass="wizardStep"
Text="Thank you for taking our survey" />
</asp:WizardStep>
</WizardSteps>
</asp:Wizard>
</asp:Content>
Example 4-11. Simulating a multipage form (.vb)
Option Explicit On Option Strict On Imports System.Web.UI.WebControls Namespace ASPNetCookbook.VBExamples ''' <summary> ''' This class provides the code behind for ''' CH04SurveyDataVB1.aspx ''' </summary> Partial Class CH04SurveyDataVB1 Inherits System.Web.UI.Page '''******************************************************************** ''' <summary> ''' This routine provides the event handler for the page load event. It ''' is responsible for initializing the controls on the page. ''' </summary> ''' ''' <param name="sender">Set to the sender of the event</param> ''' <param name="e">Set to the event arguments</param>Protected Sub Page_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Me.Load Dim yesNoSelections As ArrayList Dim experienceSelections As ArrayList If (Not Page.IsPostBack) Then 'build the arraylist with the yes/no responses yesNoSelections = New ArrayList() yesNoSelections.Add(New ListItem("Yes", "1")) yesNoSelections.Add(New ListItem("No", "0")) 'bind the yes/no data to the radio button lists in the questions rbStep1.DataSource = yesNoSelections rbStep1.DataTextField = "Text" rbStep1.DataValueField = "Value" rbStep1.DataBind() rbStep3.DataSource = yesNoSelections rbStep3.DataTextField = "Text" rbStep3.DataValueField = "Value" rbStep3.DataBind() 'build the arraylist with the experience responses experienceSelections = New ArrayList experienceSelections.Add(New ListItem("-- Select One --", "0")) experienceSelections.Add(New ListItem("0-6 Months", "1")) experienceSelections.Add(New ListItem("7-12 Months", "2")) experienceSelections.Add(New ListItem("13-24 Months", "3")) experienceSelections.Add(New ListItem("24+ Months", "4")) 'bind the experience data to the radio button lists in the questions ddStep2.DataSource = experienceSelections ddStep2.DataTextField = "Text" ddStep2.DataValueField = "Value" ddStep2.DataBind() ddStep4.DataSource = experienceSelections ddStep4.DataTextField = "Text" ddStep4.DataValueField = "Value" ddStep4.DataBind() End If End Sub 'Page_Load
'''*********************************************************************** ''' <summary> ''' This routine provides the event handler for the wizard's next button ''' click event. It is responsible for altering the survey navigation as ''' as function of the answers provided ''' </summary> ''' ''' <param name="sender"></param> ''' <param name="e"></param>Protected Sub wzSurvey_NextButtonClick(ByVal sender As Object, _ ByVal e As WizardNavigationEventArgs) 'skip steps as a function of the users answers Select Case e.CurrentStepIndex Case 0 If ((rbStep1.SelectedIndex >= 0) AndAlso _ (rbStep1.SelectedItem.Text.Equals("No"))) Then 'user does not use ASP.NET 1.x so move to 2.0 question wzSurvey.MoveTo(step3) End If Case 2 If ((rbStep1.SelectedIndex >= 0) AndAlso _ (rbStep3.SelectedItem.Text.Equals("No"))) Then 'user does not use ASP.NET 2.0 so move to complete step wzSurvey.MoveTo(step5) End If Case Else 'nothing required End Select End Sub 'wzSurvey_NextButtonClick
'''********************************************************************** ''' <summary> ''' This routine provides the event handler for the wizard's prev button ''' click event. It is responsible for altering the survey navigation as ''' as function of the answers provided ''' </summary> ''' ''' <param name="sender"></param> ''' <param name="e"></param>Protected Sub wzSurvey_PreviousButtonClick(ByVal sender As Object, _ ByVal e As WizardNavigationEventArgs) 'skip steps as a function of the users answers Select Case e.CurrentStepIndex Case 2 If ((rbStep1.SelectedIndex >= 0) AndAlso _ (rbStep3.SelectedItem.Text.Equals("No"))) Then 'user does not use ASP.NET 2.0 so move to 1.x question wzSurvey.MoveTo(step1) End If Case Else 'nothing required End Select End Sub 'wzSurvey_PreviousButtonClick
'''*********************************************************************** ''' <summary> ''' This routine provides the event handler for the wizard's active step ''' changed event. It is responsible for determining if the survey is ''' complete and storing the data in the data store. ''' </summary> ''' ''' <param name="sender"></param> ''' <param name="e"></param>Protected Sub wzSurvey_ActiveStepChanged(ByVal sender As Object, _ ByVal e As System.EventArgs) 'check to see if the complete step is the active step If (wzSurvey.ActiveStepIndex = wzSurvey.WizardSteps.Count - 1) Then 'survey is complete so production application should store the data 'in an applicable data store End If End Sub 'wzSurvey_ActiveStepChanged
End Class 'CH04SurveyDataVB1 End Namespace
Example 4-12. Simulating a multipage form (.cs)
using System; using System.Collections; using System.Web.UI.WebControls; namespace ASPNetCookbook.CSExamples { /// <summary> /// This class provides the code behind for /// CH04SurveyDataCS1.aspx /// </summary> public partial class CH04SurveyDataCS1 : System.Web.UI.Page { ///****************************************************************** /// <summary> /// This routine provides the event handler for the page load event. /// It is responsible for initializing the controls on the page. /// </summary> /// /// <param name="sender">Set to the sender of the event</param> /// <param name="e">Set to the event arguments</param>protected void Page_Load(object sender, EventArgs e) { ArrayList yesNoSelections; ArrayList experienceSelections; if (!Page.IsPostBack) { // build the arraylist with the yes/no responses yesNoSelections = new ArrayList(); yesNoSelections.Add(new ListItem("Yes", "1")); yesNoSelections.Add(new ListItem("No", "0")); // bind the yes/no data to the radio button lists in the questions rbStep1.DataSource = yesNoSelections; rbStep1.DataTextField = "Text"; rbStep1.DataValueField = "Value"; rbStep1.DataBind(); rbStep3.DataSource = yesNoSelections; rbStep3.DataTextField = "Text"; rbStep3.DataValueField = "Value"; rbStep3.DataBind(); // build the arraylist with the experience responses experienceSelections = new ArrayList(); experienceSelections.Add(new ListItem("-- Select One --", "0")); experienceSelections.Add(new ListItem("0-6 Months", "1")); experienceSelections.Add(new ListItem("7-12 Months", "2")); experienceSelections.Add(new ListItem("13-24 Months", "3")); experienceSelections.Add(new ListItem("24+ Months", "4")); // bind the experience data to the radio button lists in the questions ddStep2.DataSource = experienceSelections; ddStep2.DataTextField = "Text"; ddStep2.DataValueField = "Value"; ddStep2.DataBind(); ddStep4.DataSource = experienceSelections; ddStep4.DataTextField = "Text"; ddStep4.DataValueField = "Value"; ddStep4.DataBind(); } } // Page_Load
///******************************************************************* /// <summary> /// This routine provides the event handler for the wizard's next button /// click event. It is responsible for altering the survey navigation as /// as function of the answers provided /// </summary> /// /// <param name="sender"></param> /// <param name="e"></param>protected void wzSurvey_NextButtonClick(Object sender, WizardNavigationEventArgs e) { // skip steps as a function of the users answers switch (e.CurrentStepIndex) { case 0: if ((rbStep1.SelectedIndex >= 0) && (rbStep1.SelectedItem.Text.Equals("No"))) { // user does not use ASP.NET 1.x so move to 2.0 question wzSurvey.MoveTo(step3); } break; case 2: if ((rbStep1.SelectedIndex >= 0) && (rbStep3.SelectedItem.Text.Equals("No"))) { // user does not use ASP.NET 2.0 so move to complete step wzSurvey.MoveTo(step5); } break; default: // nothing required break; } } // wzSurvey_NextButtonClick
///********************************************************************* /// <summary> /// This routine provides the event handler for the wizard's prev button /// click event. It is responsible for altering the survey navigation as /// as function of the answers provided /// </summary> /// /// <param name="sender"></param> /// <param name="e"></param>protected void wzSurvey_PreviousButtonClick(Object sender, WizardNavigationEventArgs e) { // skip steps as a function of the users answers switch (e.CurrentStepIndex) { case 2: if ((rbStep1.SelectedIndex >= 0) && (rbStep3.SelectedItem.Text.Equals("No"))) { // user does not use ASP.NET 2.0 so move to 1.x question wzSurvey.MoveTo(step1); } break; default: // nothing required break; } } // wzSurvey_PreviousButtonClick
///********************************************************************** /// <summary> /// This routine provides the event handler for the wizard's active step /// changed event. It is responsible for determining if the survey is /// complete and storing the data in the data store. /// </summary> /// /// <param name="sender"></param> /// <param name="e"></param> protected void wzSurvey_ActiveStepChanged(Object sender, System.EventArgs e) { // check to see if the complete step is the active step if (wzSurvey.ActiveStepIndex == wzSurvey.WizardSteps.Count - 1) { // survey is complete so production application should store the data // in an applicable data store } } // wzSurvey_ActiveStepChanged } // CH04SurveyDataCS1 }
Get ASP.NET 2.0 Cookbook, 2nd Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.