网站导航(多视图页面:MultiView 和 Wizard 控件)

       导航组件是所有网站的基本组件。虽然把用户从一个网页转换到另一个网页非常的容易,但创建一个整个网站适用的统一的导航系统就不那么简单了。虽然可以通过少量的链接(大量的工作)建立自己的导航系统,但何不使用 ASP.NET 已经有的内建导航系统?

       本章涉及 3 个主要概念:

  • MultiView 控件和 Wizard 控件。它们可以把若干个步骤浓缩到一个页面里,把几页的工作组合在一起简化导航。
  • 站点地图模型。它允许定义网站的导航结构并直接绑定到富控件。
  • 富导航控件。这类控件包括 TreeView 和 Menu。虽然它们并不仅仅限于导航,但它们非常适合用于导航。

ASP.NET 4 中导航的变化

  • 路由。它最初被作为 ASP.NET MVC 的一部分引入,但现在也可以用于处理 URL 并把请求重定向到合适的 Web 表单。路由的主要优点是支持更清晰、更合乎逻辑的 URL 系统,它能够让搜索引擎更轻易的发现和索引网站的内容。
  • 更灵活的向导。Wizard 控件现在支持一个全新的 LayoutTemplate,如果要用我们自己设计的布局代替内置的布局,那么它能够带给你更多的支持。
  • 更标准的菜单。Menu 控件不再使用 HTML 表,而是通过一组合理设置的 CSS 样式创建自己的布局。

多视图页面

       大多数网站把任务分解到几个页面里。例如,在一个电子商务网站里,如果往购物车里添加一个项并把它带到结账处,就需要从一个页面跳转到另一个页面。这是最简单的方式,同时也容易通过编程实现(只要通过某种状态管理技术把信息从一个页面传送到另一个页面)。

       在其他一些情形下,你可能会希望把原本在几个不同页面里的代码放到同一个页面。例如,你希望提供同一数据的不同视图,用户可以切换视图而不必离开当前页面;或者,你可能需要处理一个多步骤的小任务(好比注册账号的流程)而不希望为如何在页面间传送相关信息伤脑筋。

       使用多个页面还是在一个页面中提供多个视图,从用户的角度来说可能没什么区别。在一个设计良好的网站里,用户看到的只是采用多个视图的方式保持 URL 不变。主要的差别在于编程模型。

       使用多个页面,代码能更好的分离,但需要花更多精力处理页面如何交互(它们共享或传送信息的方式)。

       使用多个视图,你会失去代码分离的好处,但更容易为不可分解的细小任务编码。

       在 ASP.NET 1.x 里,在一个页面中建立多个视图的唯一办法是在页面中添加若干个 Panel 控件,每个面板可以代表一个视图或一个步骤,然后使用 Visible 属性进行控制。你不得不在页面里添加管理面板的额外代码,此外,它不是很健壮,一些微小的错误可能导致同时显示两个面板。

       有了 ASP.NET 4,你不必再从零开始设计自己的多视图系统,而是可以使用两个更高级的控件来帮助简化设计:MultiView 和 Wizard 。

MultiView 控件

       MultiView 是两个多视图控件中较简单的一个。就本质而言,MultiView 提供了一个声明多个视图但每次只显示其中一个的方式。MultiView  没有默认的用户界面,它和前面介绍的自定义面板的方式等效。

       创建 MultiView 的过程非常的直观,看下面示例即能明白:

<asp:MultiView ID="MultiView1" runat="server" ActiveViewIndex="0">
    <asp:View ID="View1" runat="server">
        <b>Showing View #1<br /><br /><asp:Image ID="Image1" runat="server" ImageUrl="../images/cookies.jpg" /></b>
    </asp:View>
 
    <asp:View ID="View2" runat="server">
        <b>Showing View #2</b><br /><br />Text Content.
    </asp:View>
 
    <asp:View ID="View3" runat="server">
        <b>Showing View #3</b><br /><br /><asp:Calendar ID="Calendar1" runat="server"></asp:Calendar>
    </asp:View>
</asp:MultiView>

       另外,也可以通过编程添加视图,实例化一个新的视图对象通过 Views 集合的 Add()或 AddAt()把它加入到 MultiView

       添加一些控件对 MultiView 进行测试:

image

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        DropDownList1.DataSource = MultiView1.Views;
        DropDownList1.DataTextField = "ID";
        DropDownList1.DataBind();
    }
}
 
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
    MultiView1.ActiveViewIndex = DropDownList1.SelectedIndex;
}
 
protected void MultiView1_ActiveViewChanged(object sender, EventArgs e)
{
    DropDownList1.SelectedIndex = MultiView1.ActiveViewIndex;
}

       所有按钮(Button、ImageButton、LinkButton)触发的代码逻辑当然可以手工实现,不过 ASP.NET 也提供了智能响应,只要依照下表对按钮的 CommandName 属性正确设置即可:

命令名称

MultiView 字段

描    述

PreView PreviousViewCommandName 移动到前一视图
NextView NextViewCommandName 移动到后一视图
SwitchViewByID SwitchViewByIDCommandName 移动到具有特定 ID 的视图,这个 ID 从按钮控件的 CommandArgument 属性获得
SwitchViewByIndex SwitchViewByIndexCommandName 移动到特定数字序号的视图。这个序号从按钮控件的 CommandArgument 属性获得

性能问题

       关于 MultiView 要知道的最重要的细节是:

  • 它和富数据控件(GridView、FormView 等)不同,MultiView 不是命名容器,简单地说,MultiView 中不能存在相同名称的控件,如,两个叫 textBox1 的文本框。
  • 视图里引发的事件可以很方便的配置其他视图里的控件。
  • 加入视图里的控件,和页面其他部分的控件没有什么区别。

       由于这些原因,用 MultiView 创建的页面比普通页面的负载大,这是因为整个控件模型(包括所有视图上的控件),都在每次回发时创建并持久化到视图状态里

       多数情况下,它们对性能不会有太大的影响。除非你正在通过编程处理大量的控件(此时你可能需要设置这些控件的 EnableViewState 为 false);或者你正在使用多个数据源,每次回发时所有的数据源都执行自己的查询,所有的视图都会被重新绑定(包括那些不显示的视图),为了避免这个情况可以默认控件不绑定,而通过编程来绑定,或者取消当前不可见的视图的绑定过程。

       当然,不是所有的 MultiView 都会涉及数据绑定。应用 MultiView 的理想场景是处理一组扩展的输入控件。例如,把一个调查问卷窗体分解成几个视图,这样用户不需要频繁使用滚动条了。这个场景 MultiView 会取得很好的效果,调查结束后可以读取所有视图中控件的数据。

Wizard 控件

       Wizard 控件远比 MultiView 控件更富魅力。它还支持每次显示几个视图中的一个,且还包含一系列自定义的内建行为,包括导航按钮、带有分步链接的侧栏、样式和模板。

       Wizard 控件提供导航按钮并在左边提供一个带有每个步骤链接的侧栏,设置 Wizard.DisplaySideBar 可 显示 / 隐藏 侧栏。

1. 向导步骤

属性

描    述

Title 用在侧栏作为链接显示的文字
StepType 它的值来自 WizardStepType 枚举。这个值确定步骤显示导航按钮的类型。
AllowReturn 表示用户是否可以回到这一步。如果设为 false,一旦完成这一步就再也不能返回这里。侧栏的链接对这个步骤不起作用,它的下一步骤的 Previous 按钮要么跳过这一步,要么彻底隐藏(取决于先前一个步骤的 AllowReturn 值)

       下面的向导包括 4 个步骤,它们一起组成一个问卷。问卷结束时添加了 Complete 步骤,它显示一些汇总信息。导航按钮和侧栏是自动加入的:

<asp:Wizard ID="Wizard1" runat="server" Width="448px" BackColor="#EFF3FB" BorderColor="#B5C7DE"
    BorderWidth="1px" Font-Names="Verdana" CellPadding="5" ActiveStepIndex="0" Font-Size="Small"
    OnFinishButtonClick="Wizard1_FinishButtonClick">
    <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</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>
                Company Profile</h3>
            Number of Employees:
            <asp:TextBox ID="txtEmpCount" runat="server"></asp:TextBox><br />
            Number of Locations: &nbsp;<asp:TextBox ID="txtLocCount" runat="server"></asp:TextBox>
        </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 2008</asp:ListItem>
                <asp:ListItem>Office 2007</asp:ListItem>
                <asp:ListItem>Windows Server 2008</asp:ListItem>
                <asp:ListItem>SQL Server 2008</asp:ListItem>
            </asp:CheckBoxList>
        </asp:WizardStep>
        <asp:WizardStep ID="Complete" runat="server" Title="Complete " StepType="Complete">
            <br />
            <asp:Label ID="lblSummary" runat="server" Text="Label"></asp:Label>
            <br />
            <br />
            Thank you for completing this survey.<br />
            Your products will be delivered shortly.<br />
            <br />
        </asp:WizardStep>
    </WizardSteps>
    <SideBarStyle VerticalAlign="Top" />
</asp:Wizard>

image

image

image

image

2. 向导事件

       可以编写响应几个事件的代码来增强向导,如下表:

ActiveStepChanged 控件每次切换步骤时发生。(用户点击了导航按钮 or 代码修改了 ActiveStepIndex 属性
CancelButtonClick 默认情况不会显示此按钮。设置 Wizard.DisplayCancelButton 属性可把它添加到每个步骤。通常,单击 Cancel 按钮会退出向导。如果不需要执行任何清理代码,只要设置 CancelDestinationPageUrl 属性就会自动重定向。
FinishButtonClick 不解释
NextButtonClick 不解释
PreviousButtonClick 不解释
SideBarButtonClick 不解释

       总体而言,有两种编程类型的向导编程模型:

  • 逐步提交如果每个步骤包括一个不可回撤的原子操作,应采取这种方式。例如,如果处理的订单信息涉及信用卡授权,在这之后是最终的购买,你就不能允许用户回退到上一步重新编辑信用卡号。要支持这种模型,就需要把某些或所有步骤的 AllowReturn 属性设为 false,并且响应 ActiveStepChanged 事件为每个步骤提交变更。
  • 最后提交。如果每个步骤都是为最后要执行的操作收集数据,应使用这种方式。例如,收集用户信息进行注册。最后可以响应 FinishButtonClick 事件。

       上一示例,响应了 FinishButtonClick 事件,最后呈现了一个信息的汇总:

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();
}

       如果希望知道用户在向导里执行的是哪一步骤,可以使用 Wizard.GetHistory()方法。它返回目前已经被访问的 WizardStepBase 对象集合,按时间反向排序。也就是说,集合的第一项代表前一个步骤,以此类推。

3. 向导样式、模板、布局

       毫无疑问,Wizard 控件最强大的功能是允许定制外观,根据希望对外观修改程度的不同,你有不同的选择。对于不大的修改,可以设置各种最上层的属性。例如,和其他 ASP.NET 控件一样,可以控制颜色、字体、空格、边框样式等。

       利用样式可以获得更多控制。和其他基于样式的控件一样,样式冲突时,较具体的样式(如 SideBarStyle、StartNextButtonStyle)会覆盖(ControlStyle、NavigationButtonStyle)。

ControlStyle 作用于 Wizard 控件的所有区域
HeaderStyle 作用于 Wizard 控件的所有区域,它只在设置了 HeaderText 属性后可见
SideBarStyle 作用于 Wizard 控件的所有区域
SideBarButtonStyle 只作用于侧栏里的按钮
StepStyle 作用于控件中定义步骤内容的区域
NavigationStyle 作用于控件底部显示的导航按钮的区域
NavigationButtonStyle 只作用于导航区域的导航按钮
StartNextButtonStyle 作用于第一个步骤里的“下一步”导航按钮(StepType 为 Start 时)
StepNextButtonStyle 作用于中间步骤的“下一步”导航按钮(StepType 为 Step 时)
StepPreviousButtonStyle 作用于中间步骤的“上一步”导航按钮(StepType 为 Step 时)
FinishPreviousButtonStyle 作用于最后一个步骤里的“上一步”导航按钮(StepType 为 Finish 时)
CancelButtonStyle 如果把 Wizard.DisplayCancelButton 设为 true,它作用于“取消”按钮

       如果不能通过属性和样式表达到期望的自定义级别,还可以借助模板完全定义 Wizard 控件的外观。如标题、侧栏、按钮等。所有的模板都是独立于步骤内容而声明的。下表显示模板的完整列表:

HeaderTemplate 定义标题区域的内容
SideBarTemplate 定义侧栏,通常它包含每个步骤的导航链接
StartNavigationTemplate 定义第一个步骤的导航按钮
StepNavigationTemplate 定义中间步骤的导航按钮
FinishNavigationTemplate 定义最后一个步骤的导航按钮
LayoutTemplate 定义标题、侧栏、步骤区域、导航按钮的总体布置

       下面这个标题模板使用数据绑定表达式显示当前步骤的标题:

</WizardSteps>
    ...
</WizardSteps>
 
<HeaderTemplate>
    <i>Header Template</i> - <b><%= Wizard1.ActiveStep.Title %></b><br /><br />
</HeaderTemplate>

       还可以加入下列模版来定制导航按钮。这个示例保留了标准按钮(通过显式声明)并加入了一些斜体文字,这样你可以看到每个模板什么时候在使用:

<StartNavigationTemplate>
    <i>StartNavigationTemplate</i><br />
    <asp:Button ID="StartNextButton" runat="server" CommandName="MoveNext" Text="Next" />
</StartNavigationTemplate>
<StepNavigationTemplate>
    <i>StepNavigationTemplate</i><br />
    <asp:Button ID="StepPreviousButton" runat="server" CausesValidation="False" CommandName="MovePrevious"
        Text="Previous" />
    <asp:Button ID="StepNextButton" runat="server" CommandName="MoveNext" Text="Next" />
</StepNavigationTemplate>
<FinishNavigationTemplate>
    <i>FinishNavigationTemplate</i><br />
    <asp:Button ID="FinishPreviousButton" runat="server" CausesValidation="False" CommandName="MovePrevious"
        Text="Previous" />
    <asp:Button ID="FinishButton" runat="server" CommandName="MoveComplete" Text="Finish" />
</FinishNavigationTemplate>

       使用模板的秘诀在于确保使用正确的命令名,这样 Wizard 控件可以关联到标准逻辑(否则,你将不得不自己实现导航和排序的代码,它们冗长且易出错)。如果你不太确定要使用什么样的命令名,可以利用智能标签中的转换模板来看一看。

       验证控件也可以毫无问题的在 Wizard 里使用。如果验证控件发现了无效数据,它会阻止用户单击侧栏的所有链接并防止用户单击“下一步”继续操作

      

       最后,你可以使用 LayoutTemplate 模板来突破目前所见到的所有的基于表格的结构。从本质上,通过 LayoutTemplate 可以告诉 ASP.NET 如何对各个模板进行相对定位。借助正确的 PlaceHolder 控件插入各个模板:

<LayoutTemplate>
    <asp:PlaceHolder ID="navigationPlaceHolder" runat="server" />
    <asp:PlaceHolder ID="sideBarPlaceHolder" runat="server" />
    <asp:PlaceHolder ID="WizardStepPlaceHolder" runat="server" />
    <asp:PlaceHolder ID="headerPlaceHolder" runat="server" />
</LayoutTemplate>

       为了获得更理想的布局,还需要把各个 PlaceHolder 对象放到表格的单元格里或者放到通过 CSS 样式属性定位的 <div> 元素里。

原文地址:https://www.cnblogs.com/SkySoot/p/2729743.html