母版页和站点导航 (C#)

作者 :斯科特·米切尔

下载 PDF

用户友好的网站的一个常见特征是,它们具有一致的网站范围页面布局和导航方案。 本教程介绍如何跨所有可以轻松更新的页面创建一致的外观。

介绍

用户友好的网站的一个常见特征是,它们具有一致的网站范围页面布局和导航方案。 ASP.NET 2.0 引入了两项新功能,可大大简化实现网站范围的页面布局和导航方案:母版页和网站导航。 母版页允许开发人员创建具有指定可编辑区域的网站范围模板。 然后,可以将此模板应用于网站中的 ASP.NET 页面。 此类 ASP.NET 页面只需要为母版页的指定可编辑区域提供内容,母版页中所有其他标记在使用母版页的所有 ASP.NET 页中完全相同。 此模型允许开发人员定义和集中网站范围的页面布局,从而更轻松地在所有可以轻松更新的页面上创建一致的外观。

网站导航系统为页面开发人员提供一种机制,用于定义网站地图,并为要以编程方式查询的站点地图提供 API。 新的导航 Web 控件 Menu、TreeView 和 SiteMapPath,可以轻松地在统一导航界面呈现站点地图的全部或部分。 我们将使用默认网站导航提供程序,这意味着我们的网站地图将以 XML 格式的文件定义。

为了说明这些概念并使教程网站更易于使用,让我们在本课中定义网站范围的页面布局、实现网站地图以及添加导航 UI。 在本教程结束时,我们将有一个完善的网站设计来构建我们的教程网页。

本教程的结束结果

图 1:本教程的最终结果(单击以查看全尺寸图像

步骤 1:创建母版页

第一步是创建网站的母版页。 现在,我们的网站仅包含类型化数据集(位于 App_Code 文件夹中)、BLL 类(位于 App_Code 文件夹中的 ProductsBLL.csCategoriesBLL.cs 等等)、数据库(位于 App_Data 文件夹中的 NORTHWND.MDF)、配置文件(Web.config)和 CSS 样式表文件(Styles.css)。 我从前两个教程中清理了这些页面和文件,演示如何使用 DAL 和 BLL,因为我们将在将来的教程中更详细地重新介绍这些示例。

项目中的文件

图 2:项目中的文件

若要创建母版页,请在解决方案资源管理器中右键单击项目名称,然后选择“添加新项”。 然后从模板列表中选择母版页类型并将其命名 Site.master

向网站添加新母版页

图 3:向网站添加新母版页(单击可查看全尺寸图像

在母版页中在此处定义网站范围的页面布局。 可以使用“设计”视图并添加所需的任何布局或 Web 控件,也可以手动在源视图中手动添加标记。 在我的母版页中,我使用 级联样式表 用于定位和设置样式,CSS 设置定义在外部文件 Style.css 中。 虽然无法从下面所示的标记中判断,但定义了 CSS 规则,以便导航 <div>的内容绝对定位,使其显示在左侧,且宽度固定为 200 像素。

Site.master

<%@ Master Language="C#" AutoEventWireup="true"
    CodeFile="Site.master.cs" Inherits="Site" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Working with Data Tutorials</title>
    <link href="Styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <div id="wrapper">

        <form id="form1" runat="server">

            <div id="header">
                <span class="title">Working with Data Tutorials</span>
                <span class="breadcrumb">
                 TODO: Breadcrumb will go here...</span>
            </div>

            <div id="content">
                <asp:contentplaceholder id="MainContent"
                 runat="server">
                  <!-- Page-specific content will go here... -->
                </asp:contentplaceholder>
            </div>

            <div id="navigation">
                TODO: Menu will go here...
            </div>
        </form>
    </div>
</body>
</html>

母版页定义静态页面布局和可由使用母版页的 ASP.NET 页编辑的区域。 这些内容可编辑区域由 ContentPlaceHolder 控件指示,可在内容 <div>中查看。 我们的母版页具有单个 ContentPlaceHolder(MainContent),但母版页可能有多个 ContentPlaceHolder。

输入上述标记后,切换到“设计”视图会显示母版页的布局。 使用此母版页的任何 ASP.NET 页面都将具有此统一布局,并能够指定 MainContent 区域的标记。

在设计视图中查看时的母版页

图 4:母版页,通过设计视图查看时(单击以查看全尺寸图像

步骤 2:将主页添加到网站

定义母版页后,即可为网站添加 ASP.NET 页。 我们先来添加网站主页Default.aspx。 右键单击解决方案资源管理器中的项目名称,然后选择“添加新项”。 从模板列表中选择“Web 表单”选项,并命名该文件 Default.aspx。 此外,选中“选择母版页”复选框。

添加新 Web 窗体,选中“选择母版页”复选框

图 5:添加新 Web 窗体,选中“选择母版页”复选框(单击以查看全尺寸图像

单击“确定”按钮后,系统会要求选择此新 ASP.NET 页面应使用的母版页。 虽然项目中可以有多个母版页,但我们只有一个母版页。

选择此 ASP.NET 页应使用的母版页

图 6:选择本 ASP.NET 页应使用的母版页(单击可查看全尺寸图像

选取母版页后,新的 ASP.NET 页将包含以下标记:

Default.aspx

<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
    CodeFile="Default.aspx.cs" Inherits="_Default" Title="Untitled Page" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent"
  Runat="Server">
</asp:Content>

@Page 指令中,引用使用的母版页文件(MasterPageFile="~/Site.master"),ASP.NET 页的标记包含母版页中定义的每个 ContentPlaceHolder 控件的内容控件,该控件 ContentPlaceHolderID 将内容控件映射到特定的 ContentPlaceHolder。 内容控件用于放置要显示在相应 ContentPlaceHolder 中的标记的位置。 将 @Page 指令的属性 Title 设置为“开始”,并将一些欢迎内容添加到内容控件:

Default.aspx

<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
    CodeFile="Default.aspx.cs" Inherits="_Default" Title="Home" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent"
    Runat="Server">
    <h1>Welcome to the Working with Data Tutorial Site</h1>

    <p>This site is being built as part of a set of tutorials that
illustrate some of the new data access and databinding features in
ASP.NET 2.0 and Visual Web Developer.</p>

    <p>Over time, it will include a host of samples that
demonstrate:</p>

    <ul>
        <li>Building a DAL (data access layer),</li>
        <li>Using strongly typed TableAdapters and DataTables</li>
        <li>Master-Detail reports</li>
        <li>Filtering</li>
        <li>Paging,</li>
        <li>Two-way databinding,</li>
        <li>Editing,</li>
        <li>Deleting,</li>
        <li>Inserting,</li>
        <li>Hierarchical data browsing,</li>
        <li>Hierarchical drill-down,</li>
        <li>Optimistic concurrency,</li>
        <li>And more!</li>
    </ul>
</asp:Content>

Title指令中的@Page属性允许我们从 ASP.NET 页设置页面的标题,即使<title>元素是在母版页中定义的。 还可以使用 Page.Title 以编程方式设置标题。 另请注意,母版页对样式表(如 Style.css)的引用会自动更新,使它们能够在任意 ASP.NET 页中正常工作,而不论 ASP.NET 页相对于母版页的所在目录。

切换到“设计”视图,可以看到页面在浏览器中的外观。 请注意,在 ASP.NET 页的设计视图中,只有内容可编辑区域是可编辑的,母版页中定义的非 ContentPlaceHolder 标记显示为灰色。

ASP.NET 页面的设计视图同时显示可编辑区域和非可编辑区域

图 7:“ASP.NET”页面的设计视图显示可编辑区域和非可编辑区域(单击以查看全尺寸图像

Default.aspx浏览器访问页面时,ASP.NET 引擎会自动合并页面母版页内容和 ASP。NET 的内容,并将合并的内容呈现到发送到请求浏览器的最终 HTML 中。 更新母版页的内容时,使用此母版页的所有 ASP.NET 页将在下次请求时与新的母版页内容合并。 简言之,母版页模型允许定义单个页面布局模板(母版页),其更改会立即反映在整个网站中。

向网站添加其他 ASP.NET 页面

让我们花点时间在网站上添加额外的 ASP.NET 页面模板,这些模板将最终用于各种报告演示。 总共有超过 35 个演示项目,因此,与其创建所有临时页面,不如只创建前几页即可。 由于还存在许多类别的演示,因此为了更好地管理演示,请为类别添加文件夹。 现在添加以下三个文件夹:

  • BasicReporting
  • Filtering
  • CustomFormatting

最后,添加新文件,如图 8 中的解决方案资源管理器所示。 添加每个文件时,请记得选中“选择母版页”复选框。

添加以下文件

图 8:添加以下文件

步骤 2:创建网站地图

管理由多个页面组成的网站的挑战之一是为访问者提供一种直接的方式浏览网站。 首先,必须定义网站的导航结构。 接下来,必须将此结构转换为可导航的用户界面元素,例如菜单或痕迹导航元素。 最后,需要维护和更新整个过程,因为新页面将添加到网站并删除现有页面。 在 ASP.NET 2.0 之前,开发人员自行创建网站的导航结构、维护网站并将其转换为可导航的用户界面元素。 但是,借助 ASP.NET 2.0,开发人员可以利用非常灵活的网站导航系统。

ASP.NET 2.0 网站导航系统为开发人员定义网站地图,然后通过编程 API 访问此信息提供了一种方法。 ASP.NET 附带一个网站地图提供程序,该提供程序希望以特定方式以 XML 文件格式存储站点地图数据。 但是,由于站点导航系统是基于 提供程序模型 构建的,因此可以扩展它以支持序列化站点地图信息的替代方法。 Jeff Prosise 的文章: 你一直在等待的 SQL 站点地图提供程序 演示如何创建将站点地图存储在 SQL Server 数据库中的站点地图提供程序;另一个选项是 基于文件系统结构创建站点地图提供程序

但是,在本教程中,让我们使用随 ASP.NET 2.0 一起提供的默认站点地图提供程序。 若要创建站点地图,只需右键单击解决方案资源管理器中的项目名称,选择“添加新项”,然后选择“网站地图”选项。 将名称保留为 Web.sitemap,然后单击“添加”按钮。

将网站地图添加到项目

图 9:向项目添加网站地图(单击以查看全尺寸图像

站点地图文件是一个 XML 文件。 请注意,Visual Studio 为站点地图结构提供 IntelliSense。 站点地图文件必须具有 <siteMap> 节点作为其根节点,该节点必须仅包含一个 <siteMapNode> 子元素。 然后,第一个 <siteMapNode> 元素可以包含任意数量的后代 <siteMapNode> 元素。

定义站点映射以模拟文件系统结构。 也就是说,为这三个文件夹中的每个文件夹添加一个 <siteMapNode> 元素,以及这些文件夹中每个 ASP.NET 页的子 <siteMapNode> 元素,如下所示:

Web.sitemap

<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >

  <siteMapNode url="~/Default.aspx" title="Home" description="Home">
      <siteMapNode title="Basic Reporting"
        url="~/BasicReporting/Default.aspx"
        description="Basic Reporting Samples">
        <siteMapNode url="~/BasicReporting/SimpleDisplay.aspx"
         title="Simple Display"
         description="Displays the complete contents
          of a database table." />
        <siteMapNode url="~/BasicReporting/DeclarativeParams.aspx"
          title="Declarative Parameters"
          description="Displays a subset of the contents
            of a database table using parameters." />
        <siteMapNode url="~/BasicReporting/ProgrammaticParams.aspx"
         title="Setting Parameter Values"
         description="Shows how to set parameter values
          programmatically." />
      </siteMapNode>

      <siteMapNode title="Filtering Reports"
       url="~/Filtering/Default.aspx"
       description="Samples of Reports that Support Filtering">
        <siteMapNode url="~/Filtering/FilterByDropDownList.aspx"
          title="Filter by Drop-Down List"
          description="Filter results using a drop-down list." />
        <siteMapNode url="~/Filtering/MasterDetailsDetails.aspx"
         title="Master-Details-Details"
         description="Filter results two levels down." />
        <siteMapNode url="~/Filtering/DetailsBySelecting.aspx"
          title="Details of Selected Row"
          description="Show detail results for a selected item in a GridView." />
      </siteMapNode>

      <siteMapNode title="Customized Formatting"
         url="~/CustomFormatting/Default.aspx"
         description="Samples of Reports Whose Formats are Customized">
        <siteMapNode url="~/CustomFormatting/CustomColors.aspx"
         title="Format Colors"
         description="Format the grid s colors based
           on the underlying data." />
        <siteMapNode
          url="~/CustomFormatting/GridViewTemplateField.aspx"
          title="Custom Content in a GridView"
          description="Shows using the TemplateField to
          customize the contents of a field in a GridView." />
        <siteMapNode
          url="~/CustomFormatting/DetailsViewTemplateField.aspx"
          title="Custom Content in a DetailsView"
          description="Shows using the TemplateField to customize
           the contents of a field in a DetailsView." />
        <siteMapNode url="~/CustomFormatting/FormView.aspx"
          title="Custom Content in a FormView"
          description="Illustrates using a FormView for a
           highly customized view." />
        <siteMapNode url="~/CustomFormatting/SummaryDataInFooter.aspx"
          title="Summary Data in Footer"
          description="Display summary data in the grids footer." />
      </siteMapNode>

  </siteMapNode>

</siteMap>

网站地图定义网站的导航结构,它是描述网站的各个部分的层次结构。 每个<siteMapNode>Web.sitemap元素都表示网站导航结构中的一个部分。

站点地图表示分层导航结构

图 10:网站地图表示分层导航结构(单击以查看全尺寸图像

ASP.NET 通过 .NET Framework 的 SiteMap 类公开站点地图的结构。 此类具有一个 CurrentNode 属性,该属性返回有关用户当前正在访问的部分的信息;该 RootNode 属性返回网站地图的根目录(网站地图中的主页)。 属性CurrentNodeRootNode返回 SiteMapNode 实例,这些实例具有诸如ParentNodeChildNodesNextSiblingPreviousSibling等的属性,允许遍进站点地图层次结构。

步骤 3:基于站点地图显示菜单

可以通过编程方式访问 ASP.NET 2.0 中的数据,例如在 ASP.NET 1.x 中或通过新的 数据源控件以声明方式访问数据。 有几个内置数据源控件(例如 SqlDataSource 控件)用于访问关系数据库数据、ObjectDataSource 控件、用于从类访问数据等。 甚至可以创建自己的 自定义数据源控件

数据源控件充当 ASP.NET 页和基础数据之间的代理。 为了显示数据源控件的检索数据,我们通常会向页面添加另一个 Web 控件并将其绑定到数据源控件。 若要将 Web 控件绑定到数据源控件,只需将 Web 控件的属性 DataSourceID 设置为数据源控件 ID 的属性的值。

为了帮助处理网站地图的数据,ASP.NET 包括 SiteMapDataSource 控件,这使我们可以将 Web 控件绑定到网站的网站地图。 TreeView 和 Menu 两个 Web 控件通常用于提供导航用户界面。 若要将站点地图数据绑定到这两个控件之一,只需将 SiteMapDataSource 添加到页面,以及相应设置其属性的 DataSourceID TreeView 或 Menu 控件。 例如,可以使用以下标记将 Menu 控件添加到母版页:

<div id="navigation">
    <asp:Menu ID="Menu1" runat="server"
      DataSourceID="SiteMapDataSource1">
    </asp:Menu>

    <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" />
</div>

为了更精细地控制所发出的 HTML,我们可以将 SiteMapDataSource 控件绑定到 Repeater 控件,如下所示:

<div id="navigation">
    <ul>
        <li><asp:HyperLink runat="server" ID="lnkHome"
         NavigateUrl="~/Default.aspx">Home</asp:HyperLink></li>

        <asp:Repeater runat="server" ID="menu"
          DataSourceID="SiteMapDataSource1">
            <ItemTemplate>
                <li>
                    <asp:HyperLink runat="server"
                    NavigateUrl='<%# Eval("Url") %>'>
                    <%# Eval("Title") %></asp:HyperLink>
                </li>
            </ItemTemplate>
        </asp:Repeater>
    </ul>

    <asp:SiteMapDataSource ID="SiteMapDataSource1"
      runat="server" ShowStartingNode="false" />
</div>

SiteMapDataSource 控件一次返回站点地图层次结构一个级别,从根站点地图节点(主页,在我们的站点地图中开始),然后返回下一级(基本报告、筛选报告和自定义格式),等等。 将 SiteMapDataSource 绑定到 Repeater 时,它会枚举返回的第一个级别,并实例化 ItemTemplate 该第一个级别的每个 SiteMapNode 实例。 若要访问该控件SiteMapNode的特定属性,可以使用Eval(propertyName)此属性,这就是获取 HyperLink 控件的每个SiteMapNodeUrl属性和Title属性的方式。

上面的 Repeater 示例将呈现以下标记:

<li>
    <a href="/Code/BasicReporting/Default.aspx">Basic Reporting</a>
</li>

<li>
    <a href="/Code/Filtering/Default.aspx">Filtering Reports</a>
</li>

<li>
    <a href="/Code/CustomFormatting/Default.aspx">
     Customized Formatting</a>
</li>

这些网站地图节点(基本报告、筛选报告和自定义格式设置)构成正在呈现的网站地图 的第二 级,而不是第一个级别。 这是因为 SiteMapDataSource 的属性 ShowStartingNode 设置为 False,导致 SiteMapDataSource 绕过根站点地图节点,而是首先返回站点地图层次结构中的第二个级别。

若要显示基本报告、筛选报表和自定义格式 SiteMapNode 设置的子级,我们可以将另一个 Repeater 添加到初始 Repeater 的子 ItemTemplate级。 第二个 Repeater 将绑定到 SiteMapNode 实例 ChildNodes 的属性,如下所示:

<asp:Repeater runat="server" ID="menu" DataSourceID="SiteMapDataSource1">
    <ItemTemplate>
        <li>
            <asp:HyperLink runat="server"
             NavigateUrl='<%# Eval("Url") %>'>
             <%# Eval("Title") %></asp:HyperLink>

            <asp:Repeater runat="server"
                DataSource='<%# ((SiteMapNode) Container.DataItem).ChildNodes %>'>
                <HeaderTemplate>
                    <ul>
                </HeaderTemplate>

                <ItemTemplate>
                    <li>
                        <asp:HyperLink runat="server"
                         NavigateUrl='<%# Eval("Url") %>'>
                         <%# Eval("Title") %></asp:HyperLink>
                    </li>
                </ItemTemplate>

                <FooterTemplate>
                    </ul>
                </FooterTemplate>
            </asp:Repeater>
        </li>
    </ItemTemplate>
</asp:Repeater>

这两个重复器生成了以下标记(一些标记已被删除以简便):

<li>
    <a href="/Code/BasicReporting/Default.aspx">Basic Reporting</a>
    <ul>
       <li>
          <a href="/Code/BasicReporting/SimpleDisplay.aspx">
            Simple Display</a>
       </li>
       <li>
          <a href="/Code/BasicReporting/DeclarativeParams.aspx">
            Declarative Parameters</a>
       </li>
       <li>
          <a href="/Code/BasicReporting/ProgrammaticParams.aspx">
            Setting Parameter Values</a>
       </li>
    </ul>
</li>

<li>
    <a href="/Code/Filtering/Default.aspx">Filtering Reports</a>
    ...
</li>

<li>
    <a href="/Code/CustomFormatting/Default.aspx">
      Customized Formatting</a>
    ...
</li>

使用从Rachel Andrew的书《The CSS Anthology: 101 Essential Tips, Tricks, & Hacks》中选择的 CSS 样式,对 元素进行样式化,使得标记生成如下视觉输出:

由两个重复器和一些 CSS 组成的菜单

图 11:由两个重复器和一些 CSS 组成的菜单

此菜单位于母版页中,并绑定到由Web.sitemap定义的网站地图,这意味着对网站地图进行的任何更改都会立即在使用Site.master母版页的所有页面上反映出来。

禁用 ViewState

所有 ASP.NET 控件都可以选择将其状态保存到 视图状态,该状态在呈现的 HTML 中序列化为隐藏的窗体字段。 视图状态由控件用来在回发中记住其以编程方式更改的状态,例如绑定到数据 Web 控件的数据。 虽然视图状态允许在回发中记住信息,但它会增加必须发送到客户端的标记的大小,并且如果不受密切监视,可能会导致严重的页面膨胀。 数据 Web 控件(尤其是 GridView)对于向页面添加数十 KB 的额外标记尤其臭名昭著。 虽然对于宽带或内网用户来说,这种增加可能微不足道,但视图状态可以为拨号用户的回程时间增加几秒钟。

若要查看视图状态的影响,请访问浏览器中的页面,然后查看网页发送的源(在 Internet Explorer 中,转到“视图”菜单并选择“源”选项)。 还可以启用 页面跟踪 以查看页面上每个控件使用的视图状态分配。 视图状态信息序列化在名为__VIEWSTATE 的隐藏表单字段中,该字段位于<div>元素中,紧接着<form>标签的开头。 仅当正在使用 Web 窗体时,视图状态才会持久保存;如果 ASP.NET 页面在其声明性语法中不包含 <form runat="server">,则呈现的标记中不会有 __VIEWSTATE 隐藏的窗体字段。

由母版页生成的 __VIEWSTATE 窗体字段会向页面生成的标记添加约 1,800 字节。 这种额外的负担主要是由于 Repeater 控件,因为 SiteMapDataSource 控件的内容被持久化为视图状态。 虽然额外的 1,800 字节可能看起来不算多,但在使用包含许多字段和记录的 GridView 时,视图状态容易膨胀 10 倍甚至更多。

通过将属性设置为 EnableViewStatefalse,可以在页面或控件级别禁用视图状态,从而减少呈现的标记的大小。 由于数据 Web 控件的视图状态能够在跨回发时保持绑定到此控件的数据,因此禁用数据 Web 控件的视图状态时,在每次回发时都必须重新绑定数据。 在 ASP.NET 版本 1.x 中,这一责任落在页面开发人员的肩膀上;然而,在 ASP.NET 2.0 中,如果需要,数据 Web 控件将在每次回发时重新绑定到它们的数据源控件。

若要减少页面的视图状态,请将 Repeater 控件 EnableViewState 的属性设置为 false。 这可以通过设计器中的“属性”窗口或在源视图中以声明方式完成。 进行此更改后,Repeater 的声明性标记应如下所示:

<asp:Repeater runat="server" ID="menu" DataSourceID="SiteMapDataSource1"
    EnableViewState="False">
    <ItemTemplate>
        ... <i>ItemTemplate contents omitted for brevity</i> ...
    </ItemTemplate>
</asp:Repeater>

此更改后,页面的呈现视图状态大小已缩小到仅 52 个字节,97% 视图状态大小节省! 在本系列的教程中,我们将默认禁用数据 Web 控件的视图状态,以减少呈现的标记的大小。 在大多数示例中,该 EnableViewState 属性将设置为 false,这样设置无需提及。 唯一讨论视图状态的情况是在必须启用视图状态以使数据 Web 控件实现其预期功能的场景中。

步骤 4:添加面包屑导航

若要完成母版页,让我们向每个页面添加一个痕迹导航 UI 元素。 痕迹导航快速显示用户在站点层次结构中的当前位置。 在 ASP.NET 2.0 中添加痕迹导航很容易将 SiteMapPath 控件添加到页面;不需要任何代码。

对于我们的网站,请将此控件添加到页眉 <div>

<span class="breadcrumb">
    <asp:SiteMapPath ID="SiteMapPath1" runat="server">
    </asp:SiteMapPath>
</span>

痕迹导航显示用户正在站点地图层次结构中访问的当前页,以及站点地图节点的“上级”,一直指向根(网站地图中的主页)。

面包屑导航显示站点地图层次结构中的当前页面及其祖先页面

图 12:痕迹导航显示站点地图层次结构中的当前页及其上级

步骤 5:为每个分区添加默认页面

网站中的教程分为不同的类别“基本报告”、“筛选”、“自定义格式”等,每个类别的文件夹以及相应教程作为该文件夹中的 ASP.NET 页。 此外,每个文件夹都包含一个 Default.aspx 页面。 对于此默认页面,让我们显示当前部分的所有教程。 也就是说,在Default.aspx文件夹中,我们将有指向SimpleDisplay.aspxDeclarativeParams.aspxProgrammaticParams.aspx的链接。 在这里,我们再次可以使用 SiteMap 类和数据 Web 控件根据定义 Web.sitemap的网站地图来显示此信息。

让我们再次使用 Repeater 显示无序列表,但这次我们将显示教程的标题和说明。 由于要实现此目的的标记和代码需要为每个 Default.aspx 页面重复,因此我们可以将此 UI 逻辑封装在 用户控件中。 在网站中创建一个名为 UserControls 的文件夹,并添加一个名为 SectionLevelTutorialListing.ascx 的 Web 用户控件的新项,然后添加以下标记:

将新的 Web 用户控件添加到 UserControls 文件夹

图 13:向文件夹添加新的 Web 用户控件 UserControls单击以查看全尺寸图像

SectionLevelTutorialListing.ascx

<%@ Control Language="CS" AutoEventWireup="true"
    CodeFile="SectionLevelTutorialListing.ascx.cs"
    Inherits="UserControls_SectionLevelTutorialListing" %>
<asp:Repeater ID="TutorialList" runat="server" EnableViewState="False">
    <HeaderTemplate><ul></HeaderTemplate>
    <ItemTemplate>
        <li><asp:HyperLink runat="server"
         NavigateUrl='<%# Eval("Url") %>'
         Text='<%# Eval("Title") %>'></asp:HyperLink>
                - <%# Eval("Description") %></li>
    </ItemTemplate>
    <FooterTemplate></ul></FooterTemplate>
</asp:Repeater>

SectionLevelTutorialListing.ascx.cs

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class UserControls_SectionLevelTutorialListing : UserControl
{
    protected void Page_Load(object sender, EventArgs e)
    {
        // If SiteMap.CurrentNode is not null,
        // bind CurrentNode ChildNodes to the GridView
        if (SiteMap.CurrentNode != null)
        {
            TutorialList.DataSource = SiteMap.CurrentNode.ChildNodes;
            TutorialList.DataBind();
        }
    }
}

在前面的 Repeater 示例中,我们以声明方式将数据绑定到 SiteMap Repeater。SectionLevelTutorialListing 用户控件则通过编程的方式进行绑定。 在 Page_Load 的事件处理程序中,检查此页面的 URL 是否映射到站点地图中的节点。 如果在没有相应 <siteMapNode> 条目的页面中使用此用户控件,SiteMap.CurrentNode 将返回 null,并且不会有数据绑定到 Repeater。 假设我们有一个 CurrentNode集合,则将其 ChildNodes 集合绑定到 Repeater。 由于设置了网站地图,因此 Default.aspx 每个部分中的页面都是该部分中所有教程的父节点,因此此代码将显示所有部分教程的链接和说明,如下面的屏幕截图所示。

创建此 Repeater 后,打开 Default.aspx 每个文件夹中的页面,转到“设计”视图,只需将“用户控件”从解决方案资源管理器拖动到想要显示教程列表的设计图面上即可。

用户控件已添加到Default.aspx

图 14:已将 Default.aspx 用户控件添加到 (单击以查看全尺寸图像

列出了基本报告教程

图 15:列出了基本报告教程(单击以查看全尺寸图像

概要

定义网站地图并完成母版页后,我们现在可以为与数据相关的教程提供一致的页面布局和导航方案。 无论我们添加到网站中的页面数如何,由于此信息集中,更新网站范围的页面布局或网站导航信息是一个快速而简单的过程。 具体而言,页面布局信息是在母版页 Site.master 和网站地图中 Web.sitemap定义的。 我们不需要编写 任何 代码来实现此网站范围的页面布局和导航机制,我们在 Visual Studio 中保留了完整的 WYSIWYG 设计器支持。

完成数据访问层和业务逻辑层并定义一致的页面布局和网站导航后,我们便可以开始探索常见的报告模式。 在接下来的三个教程中,我们将介绍显示从 GridView、DetailsView 和 FormView 控件中的 BLL 检索到的数据的基本报告任务。

快乐编程!

深入阅读

有关本教程中讨论的主题的详细信息,请参阅以下资源:

关于作者

斯科特·米切尔,七本 ASP/ASP.NET 书籍的作者和 4GuysFromRolla.com 的创始人,自1998年以来一直在与Microsoft Web 技术合作。 斯科特担任独立顾问、教练和作家。 他的最新书是 《Sams Teach Yourself ASP.NET 2.0 in 24 Hours》。 可以通过 mitchell@4GuysFromRolla.com 联系到他。

特别致谢

本教程系列由许多有用的审阅者审阅。 本教程的主要审阅者是 Liz Shulok、Dennis Patterson 和希尔顿 Giesenow。 有兴趣查看即将发布的 MSDN 文章? 如果是这样,请给我写信。mitchell@4GuysFromRolla.com