3.4. Simulating Multipage Forms

Problem

You want to create a form that appears, from the user’s prospective, to consist of multiple pages, while keeping all of your code in one .aspx file and the code-behind that accompanies it.

Solution

Create one ASP.NET page. Use panels to separate the HTML for each of the “virtual” pages you wish to display, and simulate a multipage form by enabling one panel at a time. The output of a typical three-page form is shown in Figures Figure 3-1 through Figure 3-3. Example 3-13 through Example 3-15 show the .aspx and code-behind files for an application that implements this solution.

Multipage form output (page 1)

Figure 3-1. Multipage form output (page 1)

Multipage form output (page 2)

Figure 3-2. Multipage form output (page 2)

Multipage form output (page 3)

Figure 3-3. Multipage form output (page 3)

Discussion

In classic ASP, a series of questions or prompts, such as those on a survey or wizard, are typically implemented using multiple ASP pages with each submitting to the next in turn. ASP.NET allows you to submit a form to itself, which means that you have to rethink how to implement a survey, wizard, or traditionally multipart form. The solution we advocate involves defining multiple panels on a single form with the ASP:Panel control, and showing or hiding the panels as required. For example, the application we’ve written uses this technique to display a series of questions in a short survey.

Tip

Refer to Recipe 3.3 if you are determined to stick to the multiple form approach.

In our example, the .aspx file contains three panels and a Next button. The first panel contains the first question (“Do you currently use ASP.NET?”) with two radio buttons for the response. The second panel contains the second question (“How long have you been using ASP.NET?”) with a drop-down list for the response. The third panel contains a message thanking the user for taking the survey. A Next button is used to move from one panel to the next.

The code-behind contains a reference to each of the panels to provide you with the ability to show and then hide any particular panel as the survey progresses. For this example, an object, Survey, is used to save the current question number and the response to each question asked. The Survey object is marked as Serializable to allow the objects of this type to be stored in the viewstate. The class is defined as follows:

               Discussion
<System.Serializable( )> Private Class Survey
  Public currentQuestion As Integer
  Public response1 As Boolean
  Public response2 As Integer
End Class

Discussion
               [System.Serializable( )]
private class Survey 
{
  public int currentQuestion;
  public Boolean response1;
  public int response2;
}

A constant, VS_SURVEY_DATA, is used to define the name of the variable placed in the viewstate. This improves maintainability of the code, because the variable in the viewstate is accessed from several locations in the code.

In the Page_Load method, the Survey object is initialized and stored in the viewstate. The form is then set up to initially display the first question in the series.

When the Next button is clicked, the form is posted back to itself and the btnNext_Click method is executed. The first action performed is to rehydrate the Survey object from the viewstate. Next, the current question is checked to see what response should be stored and which panel should next be made visible:

  • If the first question was just answered, its response is stored in the Survey object, the question number is incremented, the Survey object is again stored in the viewstate, and the second question is made visible.

  • If the second question was just answered, its response is stored in the Survey object (more permanent storage would be used instead if this were a real application), and the thank-you panel is made visible.

This example could be extended in many ways. One enhancement would be to create a totally data-driven survey form. In the .aspx file, a panel would be needed for each type of response (free-form, yes/no, selection, etc.). In the code-behind, an XML document, database, or some other data store could be used and a collection of data defined that contains the questions, type of response, etc. Based on this data, the appropriate panel would be displayed for each question.

Another possible enhancement is that instead of collecting all of the responses and storing them in the viewstate until the survey is completed, the responses could be stored in a database or other data store as the survey proceeds. This would be a better approach if the survey is long or storing partial data is desirable.

See also

Recipe 3.3 for a multiple form approach

Example 3-13. Simulating a multipage form (.aspx)

<%@ Page Language="vb" AutoEventWireup="false" 
         Codebehind="Ch03MultiPageVB.aspx.vb" 
         Inherits="ASPNetCookbook.VBExamples.CH03MultiPageVB" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
  <head>
    <title>FormMultiPageVB</title>
    <link rel="stylesheet" href="css/ASPNetCookbook.css">
  </head>
  <body leftmargin="0" marginheight="0" marginwidth="0" topmargin="0">
    <form id="frmMultiPage" method="post" runat="server">
      <table width="100%" cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td align="center">
            <img src="images/ASPNETCookbookHeading_blue.gif">
          </td>
        </tr>
        <tr>
          <td class="dividerLine">
            <img src="images/spacer.gif" height="6" border="0"></td>
        </tr>
      </table>
      <table width="90%" align="center" border="0">
        <tr>
          <td><img src="images/spacer.gif" height="10" border="0"></td>
        </tr>
        <tr>
          <td align="center" class="PageHeading">
            MultiPage Form (VB)
          </td>
        </tr>
        <tr>
          <td><img src="images/spacer.gif" height="10" border="0"></td>
        </tr>
        <tr>
          <td align="center">
            <asp:Panel ID="pnlQuestion1" Runat="server">
                                <table width="60%" border="0">
                                  <tr>
                                    <td class="MenuItem">Do you currently use ASP.NET?</td>
                                    <td>
                                      <asp:RadioButtonList ID="radQuestion1" Runat="server" 
                                                            RepeatDirection="Horizontal" 
                                                            CssClass="MenuItem" >
                                        <asp:ListItem Value="1">
                                          Yes
                                        </asp:ListItem>
                                        <asp:ListItem Value="0" Selected="True">
                                          No
                                        </asp:ListItem>
                                      </asp:RadioButtonList>
                                    </td>
                                  </tr>
                                </table>
                              </asp:Panel>

                              <asp:Panel ID="pnlQuestion2" Runat="server">
                                <table width="80%" border="0">
                                  <tr>
                                    <td class="MenuItem">How long have you been using ASP.NET?</td>
                                    <td class="MenuItem">
                                      <select id="selQuestion2" runat="server">
                                        <option value="0">-- Select One --</option>
                                        <option value="1">0-6 Months</option>
                                        <option value="2">7-12 Months</option>
                                        <option value="3">13-24 Months</option>
                                        <option value="4">24+ Months</option>
                                      </select>
                                    </td>
                                  </tr>
                                </table>
                              </asp:Panel>

                              <asp:Panel ID="pnlThankyou" Runat="server">
                                <table width="60%" border="0">
                                  <tr>
                                    <td class="MenuItem" align="center">
                                      Thank you for taking our survey
                                    </td>
                                  </tr>
                                </table>
                              </asp:Panel>

            <br />
            <asp:ImageButton ID="btnNext" Runat="server"
                                    ImageUrl="images/buttons/button_nextQuestion.gif" />
          </td>
        </tr>
      </table>
    </form>
  </body>
</html>

Example 3-14. Simulating a multipage form code-behind (.vb)

Option Explicit On 
Option Strict On
'-----------------------------------------------------------------------------
'
'   Module Name: CH03MultiPageVB.aspx.vb
'
'   Description: This module provides the code behind for
'                CH03MultiPageVB.aspx
'
'*****************************************************************************

Namespace ASPNetCookbook.VBExamples
  Public Class CH03MultiPageVB
    Inherits System.Web.UI.Page

    'panels on the form
    Protected pnlQuestion1 As System.Web.UI.WebControls.Panel
    Protected pnlQuestion2 As System.Web.UI.WebControls.Panel
    Protected pnlThankyou As System.Web.UI.WebControls.Panel

    'control for response to question 1
    Protected radQuestion1 As System.Web.UI.WebControls.RadioButtonList

    'control for response to question 2
    Protected selQuestion2 As System.Web.UI.HtmlControls.HtmlSelect

    'buttons to navigate through survey
    Protected WithEvents btnNext As System.Web.UI.WebControls.ImageButton

    'the following class defines the container to store the survey data
                      <System.Serializable( )> Private Class Survey
                        Public currentQuestion As Integer
                        Public response1 As Boolean
                        Public response2 As Integer
                      End Class

                      'the following constant defines the variable used to store the survey
                      'data in the viewstate
                      Private VS_SURVEY_DATA As String = "SurveyData"

    '*************************************************************************
    '
    '   ROUTINE: Page_Load
    '
    '   DESCRIPTION: This routine provides the event handler for the page load
    '                event.  It is responsible for initializing the controls
    '                on the page.
    '-------------------------------------------------------------------------
    Private Sub Page_Load(ByVal sender As System.Object, _
                          ByVal e As System.EventArgs) Handles MyBase.Load
      Dim surveyData As Survey

      If (Not Page.IsPostBack) Then
                          'initialize survey data
                          surveyData = New Survey
                          surveyData.currentQuestion = 1
                          surveyData.response1 = False
                          surveyData.response2 = -1

                          'store the survey in the viewstate to use on the
                          'next submittal
                          viewstate.Add(VS_SURVEY_DATA, surveyData)

                          'make the first question visible
                          pnlQuestion1.Visible = True
                          pnlQuestion2.Visible = False
                          pnlThankyou.Visible = False
                        End If
    End Sub  'Page_Load

    '*************************************************************************
    '
    '   ROUTINE: btnNext_Click
    '
    '   DESCRIPTION: This routine provides the event handler for the next
    '                button click event.
    '-------------------------------------------------------------------------
    Private Sub btnNext_Click(ByVal sender As Object, _
                                                ByVal e As System.Web.UI.ImageClickEventArgs) _
                                  Handles btnNext.Click
                        Dim surveyData As Survey

                        'get the object from the viewstate with the survey data
                        surveyData = CType(viewstate.Item(VS_SURVEY_DATA), Survey)

                        Select Case surveyData.currentQuestion
                          Case 1
                            'store answer to first question
                            If (radQuestion1.SelectedItem.Value = "0") Then
                              surveyData.response1 = False
                            Else
                              surveyData.response1 = True
                            End If

                            'increment the question number
                            surveyData.currentQuestion += 1

                            'store the survey in the viewstate to use on the
                            'next submittal
                            viewstate.Add(VS_SURVEY_DATA, surveyData)

                            'make 2nd question visible
                            pnlQuestion1.Visible = False
                            pnlQuestion2.Visible = True
                          Case 2
                            'store answer to second question
                            surveyData.response2 = CInt(selQuestion2.Value)

                            'the survey is complete so store the answers per your
                            'applications required (database, etc.)

                            'make thank you panel visible
                            pnlQuestion2.Visible = False
                            pnlThankyou.Visible = True
                            btnNext.Visible = False

                          Case Else
                            'error case
                        End Select
                      End Sub  'btnNext_Click
  End Class  'CH03MultiPageVB
End Namespace

Example 3-15. Simulating a multipage form code-behind (.cs)

//----------------------------------------------------------------------------
//
//   Module Name: CH03MultiPageCS.aspx.cs
//
//   Description: This module provides the code behind for
//                CH03MultiPageCS.aspx
//
//****************************************************************************
using System;
using System.Web.UI;

namespace ASPNetCookbook.CSExamples
{
  public class CH03MultiPageCS : System.Web.UI.Page
  {
    // panels on the form
    protected System.Web.UI.WebControls.Panel pnlQuestion1;
    protected System.Web.UI.WebControls.Panel pnlQuestion2;
    protected System.Web.UI.WebControls.Panel pnlThankyou;

    // control for response to question 1
    protected System.Web.UI.WebControls.RadioButtonList radQuestion1;

    // control for response to question 2
    protected System.Web.UI.HtmlControls.HtmlSelect selQuestion2;

    // buttons to navigate through survey
    protected System.Web.UI.WebControls.ImageButton btnNext;

    // the following class defines the container to store the survey data
                      [System.Serializable( )]
                        private class Survey 
                      {
                        public int currentQuestion;
                        public Boolean response1;
                        public int response2;
                      }

                      // the following constant defines the variable used to store the survey
                      // data in the viewstate
                      private const String VS_SURVEY_DATA = "SurveyData";

    //************************************************************************
    //
    //   ROUTINE: Page_Load
    //
    //   DESCRIPTION: This routine provides the event handler for the page 
    //                load event.  It is responsible for initializing the 
    //                controls on the page.
    //------------------------------------------------------------------------
    private void Page_Load(object sender, System.EventArgs e)
    {
      Survey surveyData = null;

      // wire the next button click event
      this.btnNext.Click += new ImageClickEventHandler(this.btnNext_Click);

      if (!Page.IsPostBack)
                        {
                          // initialize survey data
                          surveyData = new Survey( );
                          surveyData.currentQuestion = 1;
                          surveyData.response1 = false;
                          surveyData.response2 = -1;

                          // store the survey in the viewstate to use on the
                          // next submittal
                          ViewState.Add(VS_SURVEY_DATA, surveyData);

                          /// make the first question visible
                          pnlQuestion1.Visible = true;
                          pnlQuestion2.Visible = false;
                          pnlThankyou.Visible = false;
                        }
    }  // Page_Load

    //************************************************************************
    //
    //   ROUTINE: btnNext_Click
    //
    //   DESCRIPTION: This routine provides the event handler for the next 
    //                button click event.
    //------------------------------------------------------------------------
    private void btnNext_Click(Object sender,
                                                 System.Web.UI.ImageClickEventArgs e)
                      {
                        Survey surveyData = null;

                        // get the object from the viewstate with the survey data
                        surveyData = (Survey)(ViewState[VS_SURVEY_DATA]);

                        switch (surveyData.currentQuestion)
                        {
                          case 1:
                            // store answer to first question
                            if (radQuestion1.SelectedItem.Value == "0")
                            {
                              surveyData.response1 = false;
                            }
                            else
                            {
                              surveyData.response1 = true;
                            }

                            // increment the question number
                            surveyData.currentQuestion ++;

                            // store the survey in the viewstate to use on the
                            // next submittal
                            ViewState.Add(VS_SURVEY_DATA, surveyData);

                            // make 2nd question visible
                            pnlQuestion1.Visible = false;
                            pnlQuestion2.Visible = true;
                            break;

                          case 2:
                            // store answer to second question
                            surveyData.response2 = System.Convert.ToInt32(selQuestion2.Value);

                            // the survey is complete so store the answers per your
                            // applications required (database, etc.)

                            // make thank you panel visible
                            pnlQuestion2.Visible = false;
                            pnlThankyou.Visible = true;
                            btnNext.Visible = false;
                            break;

                          default:
                            // error case
                            break;
                        }  // switch (surveyData.currentQuestion)
                      }  // btnNext_Click
  }  // CH03MultiPageCS
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset