Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Pro ASP.NET 2.0 In CSharp 2005 (2005) [eng]

.pdf
Скачиваний:
107
Добавлен:
16.08.2013
Размер:
29.8 Mб
Скачать

558 C H A P T E R 1 6 W E B S I T E N AV I G AT I O N

DropDownList1.DataTextField = "ID"; DropDownList1.DataBind();

}

}

And here’s the code that sets the current view based on the list index:

protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)

{

MultiView1.ActiveViewIndex = DropDownList1.SelectedIndex;

}

Figure 16-2 shows the result.

Figure 16-2. Switching views with a list control

If you want to give the views more descriptive names, you simply fill the list box by hand. Just make sure the order matches the order of views.

There’s actually no need to write this code, because the MultiView includes some built-in smarts. Like some of the rich data controls, the MultiView recognizes specific command names in button controls. (A button control is any control that implements IButtonControl, including the Button, ImageButton, and LinkButton.) If you add a button control to the view that uses one of these recognized command names, the button will have some automatic functionality. Table 16-1 lists all the recognized command names. Each command name also has a corresponding static field in the MultiView class, so you can easily get the right command name if you choose to set it programmatically.

Table 16-1. Recognized Command Names for the MultiView

Command Name

MultiView Field

Description

PrevView

PrevViewCommandName

Moves to the previous view.

NextView

NextViewCommandName

Moves to the next view.

SwitchViewByID

SwitchViewByIDCommandName

Moves to the view with a

 

 

specific ID (string name).

 

 

The ID is taken from the

 

 

CommandArgument property

 

 

of the button control.

C H A P T E R 1 6 W E B S I T E N AV I G AT I O N

559

Command Name

MultiView Field

Description

SwitchViewByIndex

SwitchViewByIndexCommandName

Moves to the view with a

 

 

specific numeric index. The

 

 

index is taken from the

 

 

CommandArgument property

 

 

of the button control.

 

 

 

To try this, add this button to your first two views (remembering to change the ID for each one):

<asp:Button ID="cmdNext" runat="server" Text="Next >" CommandName="NextView" />

And add this button to your second and third views:

<asp:Button ID="cmdPrev" runat="server" Text="< Prev" CommandName="PrevView" />

Finally, make sure the drop-down list shows the correct view when you use the buttons by adding this code to handle the MultiView.ActiveViewIndexChanged event:

protected void MultiView1_ActiveViewChanged(object sender, EventArgs e)

{

DropDownList1.SelectedIndex = MultiView1.ActiveViewIndex;

}

Now you can move from view to view using the buttons (see Figure 16-3).

Figure 16-3. Switching views with recognized command names

The Wizard Control

The Wizard control is a more glamorous version of the MultiView control. It also supports showing one of several views at a time, but it includes a fair bit of built-in yet customizable behavior, including navigation buttons, a sidebar with step links, styles, and templates.

Usually, wizards represent a single task, and the user moves linearly through them, moving from the current step to the one immediately following it (or the one immediately preceding it in the case of a correction). The ASP.NET Wizard control also supports nonlinear navigation, which means it allows you to decide to ignore a step based on the information the user supplies.

560 C H A P T E R 1 6 W E B S I T E N AV I G AT I O N

THE PERFORMANCE OF MULTIVIEW PAGES

The most important detail you need to know about the MultiView is that unlike the rich data controls (the GridView, FormsView, and so on), the MultiView is not a naming container. This means that if you add a control named textBox1 to a view, you can’t add another control named textBox1 to another view. In fact, in terms of the page model, there’s no real difference between controls you add to a view and controls in the rest of the page. Either way, the controls you create will be accessible through member variables in your page class. This means it’s easy to configure a control in the second view when an event is raised by a control in the first view.

As a result, the pages you create using the MultiView tend to be heavier than normal pages. That’s because the entire control model—including the controls from every view—is created on every postback and persisted to view state. For the most part, this won’t be a significant factor, unless you are manipulating a large number of controls programmatically (in which case you might want to turn EnableViewState off for these controls) or you are using several data sources. For example, if you have three views and each view has a different data source control, each time the page is posted back all three data source controls will perform their queries, and every view will be bound, including those that aren’t currently visible. To avoid this overhead, you can use the techniques described in Chapter 9, such as leaving your controls unbound and binding them programmatically, or canceling the binding process for views that aren’t currently visible.

Of course, not all uses of the MultiView need to involve data binding. The perfect scenario for the MultiView is an extended set of input controls—for example, an online survey form that’s split into separate views just to spare the user a lot of scrolling. This example works well with the MultiView because at the end when the survey is complete, you can read all the data from the controls of every view.

By default, the Wizard control supplies navigation buttons and a sidebar with links for each step on the left. You can hide the sidebar by setting the Wizard.DisplaySideBar property to false. Usually, you’ll take this step if you want to enforce strict step-by-step navigation and prevent the user from jumping out of sequence. You supply the content for each step using any HTML or ASP.NET controls. Figure 16-4 shows the region where you can add content to an out-of-the-box Wizard instance.

Figure 16-4. The region for step content

Wizard Steps

To create a wizard in ASP.NET, you simply define the steps and their content using <asp:WizardStep> tags. Each step takes a few basic pieces of information, as listed in Table 16-2.

C H A P T E R 1 6 W E B S I T E N AV I G AT I O N

561

Table 16-2. WizardStep Properties

Property

Description

Title

The descriptive name of the step. This name is used for the text of the links in the

 

sidebar.

StepType

The type of step, as a value from the WizardStepType enumeration. This value

 

determines the type of navigation buttons that will be shown for this step.

 

Choices include Start (shows a Next button), Step (shows Next and Previous

 

buttons), Finish (shows a Finish and Previous button), Complete (show no

 

buttons and hides the sidebar, if it’s enabled), and Auto (the step type is inferred

 

from the position in the collection). The default is Auto, which means that the

 

first step is Start, the last step is Finish, and all other steps are Step.

AllowReturn

Indicates whether the user can return to this step. If false, once the user has

 

passed this step, the user will not be able to return. The sidebar link for this step

 

will have no effect, and the Previous button of the following step will either skip

 

this step or be hidden completely (depending on the AllowReturn value of the

 

preceding steps).

 

 

The following wizard contains four steps that, taken together, represent a simple survey. The StepType adds a Complete step at the end, with a summary. The navigation buttons and sidebar links are added automatically.

<asp:Wizard ID="Wizard1" runat="server" Width="467px" BackColor="#EFF3FB" BorderColor="#B5C7DE" BorderWidth="1px"> <WizardSteps>

<asp:WizardStep ID="WizardStep1" runat="server" Title="Personal"> <h3>Personal Profile</h3>

Preferred Programming Language:

<asp:DropDownList ID="lstLanguage" runat="server"> <asp:ListItem>C#</asp:ListItem> <asp:ListItem>VB .NET</asp:ListItem> <asp:ListItem>J#</asp:ListItem> <asp:ListItem>Java</asp:ListItem> <asp:ListItem>C++</asp:ListItem> <asp:ListItem>C</asp:ListItem>

</asp:DropDownList> <br />

</asp:WizardStep>

<asp:WizardStep ID="WizardStep2" runat="server" Title="Company"> <h3>Comany Profile</h3>

Number of Employees: <asp:TextBox ID="txtEmpCount" runat="server"/> Number of Locations: <asp:TextBox ID="txtLocCount" runat="server"/>

</asp:WizardStep>

<asp:WizardStep ID="WizardStep3" runat="server" Title="Software"> <h3>Software Profile</h3>

Licenses Required:

<asp:CheckBoxList ID="lstTools" runat="server"> <asp:ListItem>Visual Studio</asp:ListItem> <asp:ListItem>Office</asp:ListItem> <asp:ListItem>Windows 2003 Server</asp:ListItem> <asp:ListItem>SQL Server 2005</asp:ListItem> <asp:ListItem>BizTalk 2004</asp:ListItem>

</asp:CheckBoxList>

</asp:WizardStep>

<asp:WizardStep ID="Complete" runat="server" Title="Complete" StepType="Complete">

562 C H A P T E R 1 6 W E B S I T E N AV I G AT I O N

<br />

Thank you for completing this survey.<br /> Your products will be delivered shortly.<br />

</asp:WizardStep>

</WizardSteps>

</asp:Wizard>

Figure 16-5 shows the wizard steps.

Figure 16-5. A wizard with four steps

Unlike the MultiView control, you can see only one step at a time in Visual Studio. To choose which step you’re currently designing, select it from the smart tag, as shown in Figure 16-6. But be warned—every time you do, Visual Studio changes the Wizard.ActiveStepIndex property to the step you choose. Make sure you set this back to 0 before you run your application so it starts at the first step.

Note Remember, when you add controls to separate steps on a wizard, they are all instantiated and persisted in view state, regardless of the current step. If you need to slim down a complex wizard, you’ll need to split it into separate pages, use the Server.Transfer() method to move from one page to the next, and tolerate a less elegant programming model.

Wizard Events

You can write the code that underpins your wizard by responding to several events (as listed in Table 16-3).

C H A P T E R 1 6 W E B S I T E N AV I G AT I O N

563

Figure 16-6. Designing a step

Table 16-3. Wizard Events

Event

Description

ActiveStepChanged

Occurs when the control switches to a new step (either because the

 

user has clicked a navigation button or your code has changed the

 

ActiveStepIndex property).

CancelButtonClick

Occurs when the Cancel button is clicked. The cancel button is not

 

shown by default, but you can add it to every step by setting the

 

Wizard.DisplayCancelButton property. Usually, a cancel button exits

 

the wizard. If you don’t have any cleanup code to perform, just set the

 

CancelDestinationPageUrl property, and the wizard will take care of

 

the redirection automatically.

FinishButtonClick

Occurs when the Finish button is clicked.

NextButtonClick and

Occurs when the Next or Previous button is clicked on any step.

PreviousButtonClick

However, because there is more than one way to move from one

 

step to the next, it’s better to handle the ActiveStepChanged event.

SideBarButtonClick

Occurs when a button in the sidebar area is clicked.

 

 

On the whole, two wizard programming models exist:

Commit-as-you-go: This makes sense if each wizard step wraps an atomic operation that can’t be reversed. For example, if you’re processing an order that involves a credit card authorization followed by a final purchase, you can’t allow the user to step back and edit the credit card number. To support this model, you set the AllowReturn property to false on some or all steps, and you respond to the ActiveStepChanged event to commit changes for each step.

Commit-at-the-end: This makes sense if each wizard step is collecting information for an operation that’s performed only at the end. For example, if you’re collecting user information and plan to generate a new account once you have all the information, you’ll probably allow a user to make changes midway through the process. You execute your code for generating the new account when the wizard is finished by reacting to the FinishButtonClick event.

564 C H A P T E R 1 6 W E B S I T E N AV I G AT I O N

To implement commit-at-the-end with the current example, just respond to the FinishButtonClick event. Here’s an example that simply displays every selection in the summary:

protected void Wizard1_FinishButtonClick(object sender, WizardNavigationEventArgs e)

{

StringBuilder sb = new StringBuilder(); sb.Append("<b>You chose: <br />"); sb.Append("Programming Language: "); sb.Append(lstLanguage.Text); sb.Append("<br />Total Employees: "); sb.Append(txtEmpCount.Text); sb.Append("<br />Total Locations: "); sb.Append(txtLocCount.Text); sb.Append("<br />Licenses Required: "); foreach (ListItem item in lstTools.Items)

{

if (item.Selected)

{

sb.Append(item.Text); sb.Append(" ");

}

}

sb.Append("</b>"); lblSummary.Text = sb.ToString();

}

For this to work, you must add a Label control named lblSummary to the summary step.

Tip If you want to find out the path the user has taken through your wizard, you can use the Wizard.GetHistory() method. It returns a collection of WizardStepBase objects that have been accessed so far, arranged in reverse chronological order. That means the first item in the collection represents the previous step, the second item represents the step before that, and so on.

Wizard Styles and Templates

Without a doubt, the Wizard control’s greatest strength is the way it lets you customize its appearance. This means that if you want the basic model (a multistep process with navigation buttons and various events), you aren’t locked into the default user interface.

Depending on how radically you want to change the wizard, you have different options. For less dramatic modifications, you can set various top-level properties. For example, you can control the colors, fonts, spacing, and border style, as you can with any ASP.NET control. You can also tweak the appearance of every button. For example, to change the Next button, you can use the following properties: StepNextButtonType (use a button, link, or clickable image), StepNextButtonText (customize the text for a button or link), StepNextButtonImageUrl (set the image for an image button), and StepNextButtonStyle (use a style from a stylesheet). You can also add a header using the HeaderText property.

More control is available through styles. You can use styles to apply formatting options to various portions of the Wizard control just as you can use styles to format different parts of rich data controls such as the GridView. Table 16-4 lists all the styles you can use. As with other style-based controls, more specific style settings (such as SideBarStyle) override more general style settings (such as ControlStyle) when they conflict. Similarly, StartNextButtonStyle overrides NavigationButtonStyle on the first step.

C H A P T E R 1 6 W E B S I T E N AV I G AT I O N

565

Table 16-4. Wizard Styles

Style

Description

ControlStyle

Applies to all sections of the Wizard control

HeaderStyle

Applies to the header section of the Wizard control, which is visible

 

only if you set some text in the HeaderText property

SideBarStyle

Applies to the sidebar area of the Wizard control

SideBarButtonStyle

Applies to just the buttons in the sidebar

StepStyle

Applies to the section of the control where you define the step

 

content

NavigationStyle

Applies to the bottom area of the control where the navigation

 

buttons are displayed

NavigationButtonStyle

Applies to just the navigation buttons in the navigation area

StartNextButtonStyle

Applies to the next navigation button on the first step (when

 

StepType is Start)

StepNextButtonStyle

Applies to the next navigation button on intermediate steps (when

 

StepType is Step)

StepPreviousButtonStyle

Applies to the previous navigation button on intermediate steps

 

(when StepType is Step)

FinishPreviousButtonStyle

Applies to the previous navigation button on the last step (when

 

StepType is Finish)

CancelButtonStyle

Applies to the cancel button, if you have Wizard.DisplayCancel-

 

Button set to true

 

 

Finally, if you can’t get the level of customization you want through properties and styles, you can use templates to completely define the appearance of the Wizard control. Ordinarily, you can supply the HTML only for the step content (as shown in Figure 16-1). With templates, you supply the HTML for one of the other regions, such as the header, sidebar, or buttons. All templates are declared separately from the step content. Figure 16-7 shows where templates fit in.

Figure 16-7. Template regions in the Wizard control

566 C H A P T E R 1 6 W E B S I T E N AV I G AT I O N

Table 16-5 shows the full list of templates.

Table 16-5. Wizard Templates

Style

Description

HeaderTemplate

Defines the content of the header region

SideBarTemplate

Defines the sidebar, which typically includes navigation links for

 

each step

StartNavigationTemplate

Defines the navigation buttons for the first step (when StepType is

 

Start)

StepNavigationTemplate

Defines the navigation buttons for intermediate steps (when

 

StepType is Step)

FinishNavigationTemplate

Defines the navigation buttons for the final step (when StepType is

 

Finish)

 

 

For example, here’s a header template that uses a data binding expression to show the title of the current step:

<asp:Wizard ID="Wizard1" runat="server" ...> <WizardSteps>

...

</WizardSteps>

<HeaderTemplate> <i>Header Template</i> -

<b><%= Wizard1.ActiveStep.Title %></b> <br /><br />

</HeaderTemplate>

</asp:Wizard>

You can also add the following templates to customize the navigation buttons. This example keeps the standard buttons (by declaring them explicitly) and adds a piece of italicized text so you can see when each template is being used.

<StepNavigationTemplate> <i>StepNavigationTemplate</i><br />

<asp:Button ID="StepPreviousButton" runat="server" CausesValidation="False" CommandName="MovePrevious"

Text="Previous" />

<asp:Button ID="StepNextButton" runat="server" Text="Next" CommandName="MoveNext" />

</StepNavigationTemplate>

<StartNavigationTemplate> <i>StartNavigationTemplate</i><br />

<asp:Button ID="StartNextButton" runat="server" Text="Next" CommandName="MoveNext" />

</StartNavigationTemplate>

<FinishNavigationTemplate> <i>FinishNavigationTemplate</i><br />

<asp:Button ID="FinishPreviousButton" runat="server" CausesValidation="False" Text="Previous" CommandName="MovePrevious" />

<asp:Button ID="FinishButton" runat="server" Text="Finish" CommandName="MoveComplete" />

</FinishNavigationTemplate>

C H A P T E R 1 6 W E B S I T E N AV I G AT I O N

567

The secret to using templates is making sure you use the right command names so that the Wizard control will hook up the standard logic. Otherwise, you’ll need to implement the navigation and sequencing code, which is tedious and error-prone. For example, clicking on a button with a command name of MoveNext automatically moves to the next step. If you are unsure about the correct command name to use, you can use a convenient shortcut. Select the Wizard control in Visual Studio, and choose one of the template generation links in the smart tag, such as Convert to StartNavigationTemplate. When you do, Visual Studio inserts a template that duplicates the default button appearance and behavior.

Site Maps

If your website has more than a handful of pages, you’ll probably need some sort of navigation system to let the user move one page to the next. As you saw in Chapter 15, you can use master pages to define a template for your site that includes a navigation bar. However, it’s still up to you to fill this navigation bar with content.

Obviously, you can use the ASP.NET toolkit of controls to implement almost any navigation system, but it still requires you to perform all the hard work. Fortunately, ASP.NET adds a new set of navigation features that you can use to dramatically simplify the task.

As with all the best ASP.NET features, ASP.NET navigation is flexible, configurable, and pluggable. It consists of three components:

A way to define the navigational structure of your website. This part is the XML site map, which is (by default) stored in a file.

A convenient way to parse the site map file and convert its information into a suitable object model. This part is performed by the SiteMapDataSource control and the XmlSiteMapProvider.

A way to use the site map information to display the user’s current position and give the user the ability to easily move from one place to another. This part is provided through the controls you bind to the SiteMapDataSource control, which can include breadcrumb links, lists, menus, and trees.

You can customize or extend each of these ingredients separately. For example, if you want to change the appearance of your navigation controls, you simply need to bind different controls to the SiteMapDataSource. On the other hand, if you want to read a different format of site map information or read it from a different location, you need to change your site map provider.

Figure 16-8 shows how these pieces fit together.

Figure 16-8. ASP.NET navigation with site maps