The <asp:Wizard> control is a container for a group of <asp:WizardStep> controls, where each WizardStep is a visible portion of a page to display. Like the MultiView control, the Wizard control reveals individual screens coded on a single page. Whereas the MultiView is especially designed for use on mobile devices with restricted screen sizes, the Wizard is designed to manage a set of data entry screens. Various input controls such as textboxes, radio buttons, checkboxes, and drop-down lists can be packaged as separate screens in a sequence of data entry steps. At the completion of this process, entered data can be saved to an external data source as captured information.
The Wizard control has a more elaborate set of properties than a MultiView, and it supports several events for scripting the data entry process. The general format for a Wizard and its WizardSteps is shown in Figure 12-28.
<asp:Wizard id="id" Runat="Server" ActiveStepIndex="stepindex" CancelButtonImageUrl="url" CancelButtonText="string" CancelButtonType="Button|LinkButton" CancelDestinationPageUrl="url" CellPadding="n" CellSpacing="n" DisplayCancelButton="False|True" DisplaySideBar="False|True" FinishDestinationPageUrl="url" FinishCompleteButtonImageUrl="url" FinishCompleteButtonText="string" FinishCompleteButtonType="Button|LinkButton" FinishPreviousButtonImageUrl="url" FinishPreviousButtonText="string" FinishPreviousButtonType="Button|LinkButton" HeaderText="string" StepNextButtonImageUrl="url" StepNextButtonText="string" StepNextButtonType="Button|LinkButton" StepPreviousButtonImageUrl="url" StepPreviousButtonText="string" StepPreviousButtonType="Button|LinkButton" StartNextButtonImageUrl="url" StartNextButtonText="string" StartNextButtonType="Button|LinkButton" CancelButtonStyle-property="value" FinishCompleteButtonStyle-property="value" FinishPreviousButtonStyle-property="value" NavigationButtonStyle-property="value" NavigationStyle-property="value" StepNextButtonStyle-property="value" StepPreviousButtonStyle-property="value" SideBarStyle-property="value" StartNextButtonStyle-property="value" StepStyle-property="value" property="value"... > <HeaderTemplate> ...controls, XHTML, and text </HeaderTemplate> <StartNavigationTemplate> ...controls, XHTML, and text </StartNavigationTemplate> <StepNavigationTemplate> ...controls, XHTML, and text </StepNavigationTemplate> <FinishNavigationTemplate> ...controls, XHTML, and text </FinishNavigationTemplate> <SideBarTemplate> <asp:DataList id="SideBarList" Runat="Server"> <ItemTemplate> <asp:Button id="SideBarButton" Runat="Server"/> or <asp:LinkButton id="SideBarButton" Runat="Server"/> </ItemTemplate> </asp:DataList> </SideBarTemplate> <WizardSteps> <asp:WizardStep id="id" Runat="Server" AllowReturn="False|True" StepType="Start|Step|Finish|Complete" Title="string" > ...controls, XHTML, and text </asp:WizardStep> ... </WizardSteps> </asp:Wizard>
Wizard Layout
It is helpful to keep in mind the general layout of a Wizard and its WizardSteps. The figure below shows the four sections that can be displayed by coding an <asp:Wizard> control enclosing five <asp:WizardStep> controls. No special layout or styling is applied except for the dotted borders indicating the Wizard and its four control sections.
A SideBar menu appears along the left side of the display. It presents a menu of links to the WizardSteps that comprise the sequence of page displays. A SideBar is optional and can be suppressed by coding the Wizard's DisplaySideBar="False" property. The SideBar is centered vertically within the total height of the Wizard.
A Header appears at the top of each WizardStep display. The easiest way to display a common heading is by coding the Wizard's HeaderText property as is done above. If no header is provided, none is displayed.
A WizardStep is a content display area coded inside an <asp:WizardStep> control. One or more WizardStep controls are coded for individual step displays. Four types of steps are recognized and coded as the control's StepType property. The single "Start" step is the first screen displayed; it contains a single button to navigate to the next step. One or more "Step" types are intermediate screens displayed in the order in which their <asp:WizardStep> controls are coded; they contain a pair of buttons to navigate to previous and next steps. A single "Finish" step is the last of the intermediate steps; it contains a button to navigate to the previous step and a button to navigate to the last step. The "Complete" step is the last screen displayed; it does not produce navigation buttons.
An id for a step is optional but must be included if the step is referenced in script. The Title property gives a text string that labels the step and automatically appears in the SideBar menu; all steps are displayed in the menu except for the "Complete" step. In the absence of a Title, the id is used to label the step in the menu. The AllowReturn="False" property is coded for a WizardStep in order to disallow return to this step following its initial display.
Below the WizardSteps is a Navigation area containing buttons to navigate to previous and next WizardSteps. The Navigation area recognizes three types of button sets. A StartNavigation button set presents a single button linking to the next step; this button is displayed along with the StepType="Start" WizardStep. A pair of "Previous" and "Next" StepNavigation buttons are displayed along with all StepType="Step" WizardSteps. A FinishNavigation button displays a "Previous" and "Finish" button; these are displayed along with the StepType="Finish" WizardStep. The Finish button automatically links to the StepType="Complete" step unless overridden by the FinishDestinationPageUrl property giving a different final page. The StepType="Complete" step does not display navigation buttons.
A "Cancel" button can be added to all steps by coding the Wizard's DisplayCancelButton="True" property. No change is made in the step being displayed when this button is clicked. It must be scripted to perform whatever processing is desired when the button is clicked.
Shown below is code for the Wizard display shown in Figure 12-29. As you can see, very little code and no scripting is needed to produce a functional Wizard. This framework can be used for any number of sequenced displays simply by changing the content appearing in the WizardStep controls.
<h3>Default Wizard Layout</h3> <asp:Wizard id="Wizard1" Runat="Server" HeaderText="Header"> <WizardSteps> <asp:WizardStep Title="Start" StepType="Start" Runat="Server"> This is the <b>Start</b> WizardStep. <br/><br/><br/> </asp:WizardStep> <asp:WizardStep Title="Step 1" StepType="Step" Runat="Server"> This is <b>Step</b> 1 WizardStep. <br/><br/> </asp:WizardStep> <asp:WizardStep Title="Step 2" StepType="Step" Runat="Server"> This is <b>Step</b> 2 WizardStep. <br/> </asp:WizardStep> <asp:WizardStep Title="Step 3" StepType="Step" Runat="Server"> This is <b>Step</b> 3 WizardStep. <br/><br/> </asp:WizardStep> <asp:WizardStep Title="Finish" StepType="Finish" Runat="Server"> This is the <b>Finish</b> WizardStep. <br/><br/><br/> </asp:WizardStep> <asp:WizardStep StepType="Complete" Runat="Server"> This is the <b>Complete</b> WizardStep. <br/><br/> </asp:WizardStep> </WizardSteps> </asp:Wizard>
Basic Layout Formatting
As mentioned, the SideBar menu is aligned on the vertical center of the height of the entire Wizard. Since the height of the WizardStep area varies depending on the amount of content it contains, the menu often slides up and down the page to keep itself center-aligned on the Wizard as you navigate from step to step. The navigation area, as well, changes its position to immediately follow the content area. Also, default buttons are aligned to the right of the Navigation area and change their sizes depending on their text labels. These movements and size changes are apparent in the previous example where the amount of displayed content changes from step to step.
To avoid this annoyance of moving controls and changing sizes, a few simple style settings can be applied to the Wizard. The following example sets specific sizes and positions of controls to keep the Wizard stable while the content changes.
The following code additions are made to the Wizard control to effect the above formatting.
<asp:Wizard id="Wizard2" Runat="Server" HeaderText="Header" HeaderStyle-Width="300" SideBarStyle-Width="70" SideBarStyle-VerticalAlign="Top" StepStyle-Width="300" StepStyle-Height="100" StepStyle-VerticalAlign="Top" NavigationStyle-Width="300" NavigationStyle-HorizontalAlign="Left" NavigationButtonStyle-Width="70" > ... </asp:Wizard>
The SideBar area is given a fixed width and is vertically aligned at the top of the Wizard. The Header, WizardStep, and Navigation areas are given fixed widths, and the WizardStep area is given a fixed height, with content aligned at the top of the area. The Navigation section sizes all buttons the same and aligns them to the left of the area.
Using Templates
Much of the formatting and styling of a Wizard can be accomplish with server style properties. For additional layout specifications, you can code templates to describe in exact detail how the various sections should appear, as is done in the following example output and code. WizardStep controls are coded the same as in previous examples with one exception. They are surrounded by a Panel that applies 5 pixels of padding surrounding their content.
<asp:Wizard id="Wizard3" Runat="Server" SideBarStyle-Width="70" SideBarStyle-VerticalAlign="Top" SideBarStyle-BackColor="#E0E0E0" StepStyle-Width="300" StepStyle-Height="130" StepStyle-VerticalAlign="Top" HeaderStyle-Height="27" HeaderStyle-BackColor="#E0E0E0" NavigationStyle-Height="27" NavigationStyle-BackColor="#E0E0E0" NavigationStyle-HorizontalAlign="Left" > <SideBarTemplate><br/> <asp:DataList id="SideBarList" Runat="Server" HeaderStyle-Font-Bold="True" HeaderStyle-HorizontalAlign="Center"> <HeaderTemplate> Steps </HeaderTemplate> <ItemTemplate> <asp:Button id="SideBarButton" CommandName="MoveTo" Font-Size="8pt" Width="60" Runat="Server"/> </ItemTemplate> </asp:DataList> </SideBarTemplate> <HeaderTemplate> <asp:Image ImageUrl="Wizard.gif" ImageAlign="AbsMiddle" Runat="Server"/> <asp:Label Text="Wizard Header" Runat="Server" Font-Size="12pt" Font-Bold="True"/> </HeaderTemplate> <StartNavigationTemplate> <asp:Button id="StartNextButton" CommandName="MoveNext" Runat="Server" Text="Next" Font-Size="8pt" Width="60"/> </StartNavigationTemplate> <StepNavigationTemplate> <asp:Button id="StepPreviousButton" CommandName="MovePrevious" Text="Prev" Font-Size="8pt" Width="60" Runat="Server"/> <asp:Button id="StepNextButton" CommandName="MoveNext" Text="Next" Font-Size="8pt" Width="60" Runat="Server"/> </StepNavigationTemplate> <FinishNavigationTemplate> <asp:Button CommandName="MovePrevious" Text="Prev" Runat="Server" Font-Size="8pt" Width="60"/> <asp:Button CommandName="MoveComplete" Text="Finish" Runat="Server" Font-Size="8pt" Width="60"/> </FinishNavigationTemplate> ... </asp:Wizard>
The SideBarMenu is formatted by coding a <SideBarTemplate>. The template must contain an <asp:DataList> control enclosing a single Button or LinkButton so the Wizard can properly format the links. The DataList must be assigned id="SideBarList", and the enclosed button must be assigned id="SideBarButton" and include CommandName="MoveTo". In this example, a <HeaderTemplate> is included in the DataList to supply a heading for the column of links. When Buttons are used as links, the final completion step is represented by a button "placeholder," since a link is never provided to this step. When LinkButtons are used, no such "ghost" link appears.
A Header is formatted with a <HeaderTemplate>. It can contain fixed text, XHTML, images, and server controls that are common to all steps.
The Navigation area is described by three templates. A <StartNavigationTemplate> describes and formats the button displayed when the StepType="Start" WizardStep is displayed. Either a Button or LinkButton is coded in the template along with other desired text, XHMTL, and controls. The button must contain CommandName="MoveNext" to start the paging sequence.
A <StepNavigationTemplate> formats buttons linking to the previous and next steps. This pair of Buttons or LinkButtons is displayed for all StepType="Step" WizardSteps. The buttons must include CommandName="MovePrevious" and CommandName="MoveNext" in order to function properly.
Templates may supply part of the layout and styling for their Wizard sections. This styling can be supplemented with server style properties. When both a server style property and a template is provided for the same property, the template style takes precedence.
In the following example, Wizard properties are substituted for templates to duplicate as closely as possible previous layout and styling. Notice that SideBar buttons cannot be changed to Buttons using style properties. Also, the graphic image cannot be displayed in the header without a HeaderTemplate. Otherwise, the same general layout can be achieved without templates.
<asp:Wizard id="Wizard4" Runat="Server" HeaderText="WizardHeader" HeaderStyle-Font-Bold="True" HeaderStyle-Width="300" HeaderStyle-Height="30" HeaderStyle-BackColor="#E0E0E0" StepStyle-Width="300" StepStyle-Height="130" StepStyle-VerticalAlign="Top" NavigationStyle-BackColor="#E0E0E0" NavigationStyle-HorizontalAlign="Left" NavigationButtonStyle-Width="60" NavigationButtonStyle-Font-Size="8pt" SideBarStyle-Width="70" SideBarStyle-VerticalAlign="Top" SideBarStyle-BackColor="#E0E0E0" > ... </asp:Wizard>
Using a Wizard for Data Entry
The Wizard control is designed primarily to collect information from users. Its screen displays typically include textboxes, radio buttons, checkboxes, and drop-down lists to solicit input data. The final step in the process often writes this data to an external data store to retain it for future processing. The following example presents a data entry form spanning five screens to collect data and a final screen to summarize input.
This Wizard setup does not use templates. All layout and styling is given in property settings for the control and in individual WizardSteps. Complete coding for the Wizard along with example WizardSteps are shown below.
<h3 style="text-align:center">ASP.NET 2.0 Exam</h3> <asp:Wizard id="Exam" Runat="Server" StepStyle-Width="400" StepStyle-Height="150" StepStyle-VerticalAlign="Top" NavigationStyle-BackColor="#E0E0E0" NavigationStyle-HorizontalAlign="Left" NavigationButtonStyle-Width="120" StartNextButtonText="Start Exam" StepPreviousButtonText="Previous Question" StepNextButtonText="Next Question" FinishPreviousButtonText="Previous Question" FinishCompleteButtonText="Submit Exam" SideBarStyle-Width="90" SideBarStyle-VerticalAlign="Top" SideBarStyle-BackColor="#E0E0E0" OnFinishButtonClick="Score_Exam" > <WizardSteps> <asp:WizardStep id="Step0" Title="Start" StepType="Start" Runat="Server"> <asp:Panel Style="padding:5px" Runat="Server"> <b>Instructions</b><br/> <br/> Please answer all questions. If you do not know the answer to a question, peek at the answer of the person sitting next to you. Also, make sure you sit next to a smart person. </asp:Panel> </asp:WizardStep> <asp:WizardStep id="Step1" Title="Question 1" StepType="Step" Runat="Server"> <asp:Panel Style="padding:5px" Runat="Server"> <table> <tr style="vertical-align:top"> <td rowspan="2">1.</td> <td>Which version of ASP.NET 2.0 is this?</td> </tr> <tr> <td> <asp:RadioButtonList id="Q1" Runat="Server"> <asp:ListItem>1.0</asp:ListItem> <asp:ListItem>1.1</asp:ListItem> <asp:ListItem>2.0</asp:ListItem> <asp:ListItem>8.0</asp:ListItem> </asp:RadioButtonList> </td> </tr> </table> </asp:Panel> </asp:WizardStep> ... <asp:WizardStep StepType="Complete" Runat="Server"> <asp:Panel Style="padding:5px" Runat="Server"> <b>Exam Completed</b><br/> <br/> Score = <asp:Label id="Score" Runat="Server"/> </asp:Panel> </asp:WizardStep> </WizardSteps> </asp:Wizard>
Wizard Events and Handlers
Recall that when the "Finish" button (the "Submit Exam" button in this example) is clicked at the StepType="Finish" step, the WizardStep with StepType="Complete" is displayed. This final step does not produce navigation buttons; it represents the last step in the process where input is completed and no opportunity exists to revisit previous steps. This completion step is where some action takes place following data entry. Therefore, it is often the step where a subprogram is called to process the input data. In the current example, the completion step reports the results of answering exam questions. Thus, prior to this final screen display, a subprogram call is needed to evaluate exam answers.
Button clicks in a Wizard trigger several events for which event handlers are provided. These events and handlers are described in the following table.
When a subprogram with the signature EventArgs is called on a button click, the argument ActiveStep is available for inspection. This argument is a reference to the WizardStep currently being displayed. You can determine, then, the Title of the current step by a reference to wizardId.ActiveStep.Title, or you can determine the id of the current step with wizardId.ActiveStep.Id, using the id of the Wizard as the object referent.
When a subprogram with the signature WizardNavigationEventArgs is called, the index of the step revealed by the click is given by the argument NextStepIndex. Thus, a script can determine the index of the currently displayed step.
In the example, at the StepType="Finish" step, when button "Submit Exam" is clicked, the StepType="Complete" step is automatically displayed. This final step displays the exam score. Before this screen is displayed, however, it is necessary to score the exam by calling subprogram Score_Exam in response to the button click. An OnFinishButtonClick="Score_Exam" event handler is coded in the Wizard to respond to this button click.
Sub Score_Exam (Src As Object, Args As WizardNavigationEventArgs) Dim RightAnswers As Integer = 0 If Q1.SelectedIndex = 2 Then RightAnswers += 1 End If If Q2.SelectedIndex = 0 Then RightAnswers += 1 End If If Q3.SelectedIndex = 0 Then RightAnswers += 1 End If If Q4.Text = "<asp:TextBox Runat=""Server""/>" Then RightAnswers += 1 End If If Q5.Text <> "" Then RightAnswers += 1 End If Score.Text = String.Format("{0:P0}", (RightAnswers / 5)) End Sub
The percentage of correct responses is displayed in a Label control on the StepType="Complete" screen. It is not necessary to display this step in script; it is automatically displayed when the Finish button is clicked.
External Data Sources and Destinations
In the above example, data entry responses are not written to an external data store. However, saving responses is easily accomplished in the OnFinishButtonClick subprogram in the same manner as other scripts open and write to external files and databases.
A Wizard cannot be associated with a data source control. Therefore, an external data source cannot automatically format steps and supply their data during displays. Still, scripts can be coded on the page to retrieve information from external data sources for binding to controls coded in any of the hard-coded steps.