Working with Wizards

 

Working with Wizards

Master pages and themes give you the power of building similar-looking, rich pages that share graphics, control layout, and even some functionality. A special type of rich page is the page that implements a wizard. More common in Windows desktop applications than in Web scenarios, wizards are typically used to break up large forms to collect user input. A wizard is a sequence of related steps, each associated with an input form and a user interface. Users move through the wizard sequentially, but they are normally given a chance to skip a step or jump back to modify some of the entered values. A wizard is conceptually pretty simple, but implementing it over HTTP connections can be tricky. Everybody involved with serious Web development can only heartily welcome the introduction of the Wizard control in ASP.NET 2.0.

An Overview of the Wizard Control

The Wizard control supports both linear and nonlinear navigation. It allows you to move backward to change values and to skip steps that are unnecessary due to previous settings or because users don't want to fill those fields. Like many other ASP.NET 2.0 controls, the Wizard supports themes, styles, and templates.

The Wizard is a composite control and automatically generates some constituent controls such as navigation buttons and panels. As you'll see in a moment, the programming interface of the control has multiple templates that provide for in-depth customization of the overall user interface. The control also guarantees that state is maintained no matter where you move backward, forward, or to a particular page. All the steps of a wizard must be declared within the boundaries of the same Wizard control. In other words, the wizard must be self-contained and not provide page-to-page navigation.

Structure of a Wizard

As shown in Figure 6-14, a wizard has four parts: header, view, navigation bar, and sidebar.

image from book
Figure 6-14: The four parts of a Wizard control.

The header consists of text you can set through the HeaderText property. You can change the default appearance of the header text by using its style property; you can also change the structure of the header by using the corresponding header template property. If HeaderText is empty and no custom template is specified, no header is shown for the wizard.

The view displays the contents of the currently active step. The wizard requires you to define each step in an <asp:wizardstep> element. An <asp:wizardstep> element corresponds to a WizardStep control. Different types of wizard steps are supported; all wizard step classes inherit from a common base class named WizardStepBase.

All wizard steps must be grouped in a single <wizardsteps> tag, as shown in the following code:

<asp:wizard runat="server" DisplaySideBar="true">   <wizardsteps>     <asp:wizardstep runat="server" steptype="auto" >       First step     </asp:wizardstep>     <asp:wizardstep runat="server" steptype="auto" >       Second step     </asp:wizardstep>     <asp:wizardstep runat="server" steptype="auto" >       Final step     </asp:wizardstep>   </wizardsteps> </asp:wizard> 

The navigation bar consists of auto-generated buttons that provide any needed functionality typically, going to the next or previous step or finishing. You can modify the look and feel of the navigation bar by using styles and templates.

The optional sidebar is used to display content in the left side of the control. It provides an overall view of the steps needed to accomplish the wizard's task. By default, it displays a description of each step, with the current step displayed in boldface type. You can customize styles and templates. Figure 6-15 shows the default user interface. Each step is labeled using the ID of the corresponding <asp:wizardstep> tag.

image from book
Figure 6-15: A wizard with the default sidebar on the left side.

Wizard Styles and Templates

You can style all the various parts and buttons of a Wizard control by using the properties listed in Table 6-4.

Table 6-4: The Wizard Control's Style Properties

Style

Description

CancelButtonStyle

Sets the style properties for the wizard's Cancel button

FinishCompleteButtonStyle

Sets the style properties for the wizard's Finish button

FinishPreviousButtonStyle

Sets the style properties for the wizard's Previous button when at the Finish step

HeaderStyle

Sets the style properties for the wizard's header

NavigationButtonStyle

Sets the style properties for navigation buttons

NavigationStyle

Sets the style properties for the navigation area

SideBarButtonStyle

Sets the style properties for the buttons on the sidebar

SideBarStyle

Sets the style properties for the wizard's sidebar

StartStepNextButtonStyle

Sets the style properties for the wizard's Next button when at the Start step

StepNextButtonStyle

Sets the style properties for the wizard's Next button

StepPreviousButtonStyle

Sets the style properties for the wizard's Previous button

StepStyle

Sets the style properties for the area where steps are displayed

The contents of the header, sidebar, and navigation bar can be further customized with templates. Table 6-5 lists the available templates.

Table 6-5: The Wizard Control's Template Properties

Style

Description

FinishNavigationTemplate

Specifies the navigation bar shown before the last page of the wizard. By default, the navigation bar contains the Previous and Finish buttons.

HeaderTemplate

Specifies the title bar of the wizard.

SideBarTemplate

Used to display content in the left side of the wizard control.

StartNavigationTemplate

Specifies the navigation bar for the first view in the wizard. By default, it contains only the Next button.

StepNavigationTemplate

Specifies the navigation bar for steps other than first, finish, or complete. By default, it contains Previous and Next buttons.

In addition to using styles and templates, you can control the programming interface of the Wizard control through a few properties.

The Wizard's Programming Interface

Table 6-6 lists the properties of the Wizard control, excluding style and template properties and properties defined on base classes.

Table 6-6: Main Properties of the Wizard Control

Property

Description

ActiveStep

Returns the current wizard step object. The object is an instance of the WizardStep class.

ActiveStepIndex

Gets and sets the 0-based index of the current wizard step.

DisplayCancelButton

Toggles the visibility of the Cancel button. The default value is false.

DisplaySideBar

Toggles the visibility of the sidebar. The default value is false.

HeaderText

Gets and sets the title of the wizard.

SkipLinkText

The ToolTip string that the control associates with an invisible image, as a hint to screen readers. The default value is Skip Navigation Links and is localized based on the server's current locale.

WizardSteps

Returns a collection containing all the WizardStep objects defined in the control.

A wizard in action is fully represented by its collection of step views and buttons. In particular, you'll recognize the following buttons: StartNext, StepNext, StepPrevious, FinishComplete, FinishPrevious, and Cancel. Each button is characterized by properties to get and set the button's image URL, caption, type, and destination URL after click. The name of a property is the name of the button followed by a suffix. The available suffixes are listed in Table 6-7.

Table 6-7: Suffixes of Button Properties

Suffix

Description

ButtonImageUrl

Gets and sets the URL of the image used to render the button

ButtonText

Gets and sets the text for the button

ButtonType

Gets and sets the type of the button: push button, image, or link button

DestinationPageUrl

Gets and sets the URL to jump to once the button is clicked

Note that names in Table 6-7 do not correspond to real property names. You have the four properties in this table for each distinct type of wizard button. The real name is composed by the name of the button followed by any of the suffixes for example, CancelButtonText, FinishCompleteDestinationPageUrl, and so on.

The Wizard control also supplies a few interesting methods for example, GetHistory, which is defined as follows:

public ICollection GetHistory() 

GetHistory returns a collection of WizardStepBase objects. The order of the items is determined by the order in which the wizard's pages were accessed by the user. The first object returned the one with an index of 0 is the currently selected wizard step. The second object represents the view before the current one, and so on.

The second method, MoveTo, is used to move to a particular wizard step. The method's prototype is described here:

public void MoveTo(WizardStepBase step) 

The method requires you to pass a WizardStepBase object, which can be problematic. However, the method is a simple wrapper around the setter of the ActiveStepIndex property. If you want to jump to a particular step and not hold an instance of the corresponding WizardStep object, setting ActiveStepIndex is just as effective.

Table 6-8 lists the key events in the life of a Wizard control in an ASP.NET 2.0 page.

Table 6-8: Events of the Wizard Control

Event

Description

ActiveViewChanged

Raised when the active step changes

CancelButtonClick

Raised when the Cancel button is clicked

FinishButtonClick

Raised when the Finish Complete button is clicked

NextButtonClick

Raised when any Next button is clicked

PreviousButtonClick

Raised when any Previous button is clicked

SideBarButtonClick

Raised when a button on the sidebar is clicked

As you can see, there's a common click event for all Next and Previous buttons you can find on your way. A Next button can be found on the Start page as well as on all step pages. Likewise, a Previous button can be located on the Finish page. Whenever a Next button is clicked, the page receives a NextButtonClick event; whenever a Previous button is clicked, the control raises a PreviousButtonClick event.

Adding Steps to a Wizard

A WizardStep object represents one of the child views that the wizard can display. The WizardStep class ultimately derives from View and adds just a few public properties to it. A View object represents a control that acts as a container for a group of controls. A view is hosted within a MultiView control. (See Chapter 4.) To create its output, the wizard makes internal use of a MultiView control. However, the wizard is not derived from the MultiView class.

You define the views of a wizard through distinct instances of the WizardStep class, all grouped under the <WizardSteps> tag. The <WizardSteps> tag corresponds to the WizardSteps collection property exposed by the Wizard control:

<WizardSteps>     <asp:WizardStep>         ...     </asp:WizardStep>     <asp:WizardStep>         ...     </asp:WizardStep> </WizardSteps> 

Each wizard step is characterized by a title and a type. The Title property provides a brief description of the view. This information is not used unless the sidebar is enabled. If the sidebar is enabled, the title of each step is used to create a list of steps. If the sidebar is enabled but no title is provided for the various steps, the ID of the WizardStep objects is used to populate the sidebar, as shown earlier in Figure 6-15.

While defining a step, you can also set the AllowReturn property, which indicates whether the user is allowed to return to the current step from a subsequent step. The default value of the property is true.

Types of Wizard Steps

The StepType property indicates how a particular step should be handled and rendered within a wizard. Acceptable values for the step type come from the WizardStepType enumeration, as listed in Table 6-9.

Table 6-9: Wizard Step Types

Property

Description

Auto

The default setting, which forces the wizard to determine how each contained step should be treated.

Complete

The last page that the wizard displays, usually after the wizard has been completed. The navigation bar and the sidebar aren't displayed.

Finish

The last page used for collecting user data. It lacks the Next button, and it shows the Previous and Finish buttons.

Start

The first screen displayed, with no Previous button.

Step

All other intermediate pages, in which the Previous and Next buttons are displayed.

When the wizard is in automatic mode the default type Auto it determines the type of each step based on the order in which the steps appear in the source code. For example, the first step is considered of type Start and the last step is marked as Finish. No Complete step is assumed. If you correctly assign types to steps, the order in which you declare them in the .aspx source is not relevant.

Creating an Input Step

The following code shows a sample wizard step used to collect the provider name and the connection string to connect to a database and search for some data. For better graphical results, the content of the step is encapsulated in a fixed-height <div> tag. If all the steps are configured in this way, users navigating through the wizard won't experience sudden changes in the overall page size and layout.

<asp:wizardstep  runat="server" title="Connect">     <div style="height:200px;width:400px;margin:10;">         <table>             <tr><td>Provider</td><td>                 <asp:textbox runat="server"  width="250px"                              text="System.Data.SqlClient" />             </td></tr>             <tr><td>Connection String</td><td>                 <asp:textbox runat="server"  width="250px"                     text="SERVER=(local);DATABASE=northwind;UID= ;" />             </td></tr>             <tr><td height="100px"></td></tr>         </table>     </div> </asp:wizardstep> 

Figure 6-16 shows a preview of the step. As you can guess, the step is recognized as a Start step. As a result, the wizard is added only to the Next button.

image from book
Figure 6-16: A sample Start wizard step.

A wizard is usually created for collecting input data, so validation becomes a critical issue. You can validate the input data in two nonexclusive ways using validators and using transition event handlers.

The first option involves placing validator controls in the wizard step. This guarantees that invalid input empty fields or incompatible data types is caught quickly and, optionally, already on the client:

<asp:requiredfieldvalidator  runat="server"     text="*"     errormessage="Must indicate a connection string"     setfocusonerror="true"     controltovalidate="ConnString" /> 

If you need to access server-side resources to validate the input data, you're better off using transition event handlers. A transition event is an event the wizard raises when it is about to switch to another view. For example, the NextButtonClick event is raised when the user clicks the Next button to jump to the subsequent step. You can intercept this event, do any required validation, and cancel the transition if necessary. We'll return to this topic in a moment.

Defining the Sidebar

The sidebar is a left-side panel that lists buttons to quickly and randomly reach any step of the wizard. It's a sort of quick-launch menu for the various steps that form the wizard. You control the sidebar's visibility through the Boolean DisplaySideBar attribute and define its contents through the SideBarTemplate property.

Regardless of the template, the internal layout of the sidebar is not left entirely to your imagination. In particular, the <SideBarTemplate> tag must contain a DataList control with a well-known ID SideBarList. In addition, the <ItemTemplate> block must contain a button object with the name of SideBarButton. The button object must be any object that implements the IButtonControl interface.

Note 

For better graphical results, you might want to use explicit heights and widths for all steps and the sidebar as well. Likewise, the push buttons in the navigation bar might look better if they are made the same size. You do this by setting the Width and Height properties on the NavigationButtonStyle object.

Navigating Through the Wizard

When a button is clicked to move to another step, an event is fired to the hosting page. It's up to you to decide when and how to perform any critical validation, such as deciding whether conditions exist to move to the next step.

In most cases, you'll want to perform server-side validation only when the user clicks the Finish button to complete the wizard. You can be sure that whatever route the user has taken within the wizard, clicking the Finish button will complete it. Any code you bind to the FinishButtonClick event is executed only once, and only when strictly necessary.

By contrast, any code bound to the Previous or Next button executes when the user moves back or forward. The page posts back on both events.

Filtering Page Navigation with Events

You should perform server-side validation if what the user can do next depends on the data he or she entered in the previous step. This means that in most cases you just need to write a NextButtonClick event handler:

<asp:wizard runat="server"      OnNextButtonClick="OnNext">     ... </asp:wizard> 

If the user moves back to a previously visited page, you can usually ignore any data entered in the current step and avoid validation. Because the user is moving back, you can safely assume he or she is not going to use any fresh data. When a back movement is requested, you can assume that any preconditions needed to visit that previous page are verified. This happens by design if your users take a sequential route.

If the wizard's sidebar is enabled, users can jump from page to page in any order. If the logic you're implementing through the wizard requires that preconditions be met before a certain step is reached, you should write a SideBarButtonClick event handler and ensure that the requirements have been met.

A wizard click event requires a WizardNavigationEventHandler delegate:

public delegate void WizardNavigationEventHandler(     object sender,     WizardNavigationEventArgs e); 

The WizardNavigationEventArgs structure contains two useful properties that inform you about the 0-based indexes of the page being left and the page being displayed. The CurrentStepIndex property returns the index of the last page visited; the NextStepIndex returns the index of the next page. Note that both properties are read-only.

The following code shows a sample handler for the Next button. The handler prepares a summary message to show when the user is going to the Finish page.

void OnNext(object sender, WizardNavigationEventArgs e) {     // Collect the input data if going to the last page     // -1 because of 0-based indexing, add -1 if you have a Complete page     if (e.NextStepIndex == QueryWizard.WizardSteps.Count - 2)         PrepareFinalStep(); } void PrepareFinalStep() {     string cmdText = DetermineCommandText();     // Show a Ready-to-go message     StringBuilder sb = new StringBuilder("");     sb.AppendFormat("You're about to run: <br><br>{0}<hr>", cmdText);     sb.Append("<b><br>Ready to go?</b>");     ReadyMsg.Text = sb.ToString(); } string DetermineCommandText() {     // Generate and return command text here } 

Each page displayed by the wizard is a kind of panel (actually, a view) defined within a parent control the wizard. This means that all child controls used in all steps must have a unique ID. It also means that you can access any of these controls just by name. For example, if one of the pages contains a text box named, say, ProviderName, you can access it from any event handler by using the ProviderName identifier.

The preceding code snippet is an excerpt from a sample wizard that collects input and runs a database query. The first step picks up connection information, whereas the second step lets users define table, fields, and optionally a WHERE clause. The composed command is shown in the Finish page, where the wizard asks for final approval. (See Figure 6-17.)

The full source code of the wizard is in the companion code for this book.

image from book
Figure 6-17: Two successive pages of the sample wizard query details and the Finish step.

Canceling Events

The WizardNavigationEventArgs structure also contains a read/write Boolean property named Cancel. If you set this property to true, you just cancel the ongoing transition to the destination page. The following code shows how to prevent the display of the next step if the user is on the Start page and types in sa as the user ID:

void OnNext(object sender, WizardNavigationEventArgs e) {     if (e.CurrentStepIndex == 0 &&         ConnString.Text.IndexOf("UID=sa") > -1)     {         e.Cancel = true;         return;     } } 

You can cancel events from within any transition event handler and not just from the NextButtonClick event handler. This trick is useful to block navigation if the server-side validation of the input data has failed. In this case, though, you're responsible for showing some feedback to the user.

Note 

You can't cancel navigation from within the ActiveViewChanged event. This event follows any transition events, such as the NextButtonClick or PreviousButtonClick event, and occurs when the transition has completed. Unlike transition events, the ActiveViewChanged event requires a simpler, parameterless handler EventHandler.

Finalizing the Wizard

All wizards have some code to execute to finalize the task. If you use the ASP.NET 2.0 Wizard control, you place this code in the FinishButtonClick event handler. Figure 6-18 shows the final step of a wizard that completed successfully.

void OnFinish(object sender, WizardNavigationEventArgs e) {     string finalMsg = "The operation completed successfully.";     try {         // Complete the wizard (compose and run the query)         string cmd = DetermineCommandText();         DataTable table = ExecuteCommand(ConnString.Text, cmd);         grid.DataSource = table;         grid.DataBind();         // OK color         FinalMsg.ForeColor = Color.Blue;     }     catch (Exception ex) {         FinalMsg.ForeColor = Color.Red;         finalMsg = String.Format("The operation cannot be completed                                   due to:<br>{0}", ex.Message);     }     finally {         FinalMsg.Text = finalMsg;     } } string DetermineCommandText() {     // Generate and return command text here } DataTable ExecuteCommand() {     // Execute database query here } 

image from book
Figure 6-18: The final step of a wizard that completed successfully.

If the wizard contains a Complete step, that page should be displayed after the Finish button is clicked and the final task has completed. If something goes wrong with the update, you should either cancel the transition to prevent the Complete page from even appearing or adapt the user interface of the completion page to display an appropriate error message. Which option you choose depends on the expected behavior of the implemented operation. If the wizard's operation can fail or succeed, you let the wizard complete and display an error message in case something went wrong. If the wizard's operation must complete successfully unless the user quits, you should not make the transition to the Complete page; instead, provide users with feedback on what went wrong and give them a chance to try again.

 


Programming Microsoft ASP. Net 2.0 Core Reference
Programming Microsoft ASP.NET 2.0 Core Reference
ISBN: 0735621764
EAN: 2147483647
Year: 2004
Pages: 112
Authors: Dino Esposito
BUY ON AMAZON

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net