65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET 2.0 illustrated - 第2章:真的这么简单吗?

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.75/5 (9投票s)

2006年7月20日

26分钟阅读

viewsIcon

68599

本章以场景为基础,演示了一个开发者在满足虚构客户需求的一天中的工作。

book.jpg

作者 Alex Homer, Dave Sussman
标题 ASP.NET 2.0 Illustrated
出版社 Addison-Wesley
出版日期 2006年6月6日
ISBN 0321418344
价格 49.49美元
页数 800

第2章:真的这么简单吗?

在上一章中,您已经了解了ASP.NET 2.0包含了大量新功能,这些功能减少了您需要编写的代码,并在构建动态交互式网页和应用程序时为您节省了时间和精力。为了进一步说明这一点,并让您更好地了解所有这些功能如何结合起来提供整体的ASP.NET 2.0开发体验,本章将以场景为基础,演示一个开发者在满足虚构客户需求的一天中的工作。

尽管这可能看起来是一种人为的方法,但它实际上遵循了根据用户需求不断演进应用程序的一般过程。更重要的是,它向您展示了ASP.NET 2.0中的所有各种功能如何协同工作并相互作用,从而提高您的生产力并简化开发过程。在此过程中,您将看到实现以下目标所需的步骤:

  • 使用数据源控件和GridView显示数据

  • 启用行的排序和分页

  • 提供行编辑功能

  • 添加筛选以选择特定行集

  • 以表单形式显示单行以进行编辑

  • 使用业务对象公开的数据

  • 缓存数据以减少数据库访问

  • 使用主页以提供一致的外观和感觉

  • 添加菜单和其他导航功能

在本章结束时,您将对ASP.NET 2.0中的主要功能有一个很好的理解,这些功能将大大简化您作为开发人员的工作。

开发者的一天

上午九点半,你的第二杯咖啡刚开始起作用,电话就响了。电话那头是AdventureWorks Trading Inc.的CEO玛格丽特,她没有心情闲聊。看来,尽管他们喜欢你为他们创建的新网站,但他们刚刚发现没有页面供员工查看产品列表。于是你承诺提供一个,喝完剩下的冷咖啡,然后启动Visual Studio 2005。

使用数据源控件和GridView显示数据

要构建几乎所有类型的数据访问页面,您需要能够从数据库获取数据并将其显示在网页中。在ASP和ASP.NET的早期版本中,您会考虑创建数据库连接,构建Recordset或填充DataSet,然后遍历行以创建HTML表(在ASP 3.0中),或者利用ASP.NET 1.x中的服务器端数据绑定。

然而,在ASP.NET 2.0中,这个过程要简单得多。您首先使用“服务器资源管理器”窗口(或Visual Web Developer中的“数据库资源管理器”窗口)来创建数据库连接(参见图2.1)。

图2.1 连接到数据库

现在您已经可以访问数据库了,您需要一个新的网页。这将是您已构建的现有AdventureWorks网站的一部分,因此您必须首先打开该网站。Visual Studio 2005和Visual Web Developer允许您使用多种技术打开现有网站——包括直接从文件系统、通过HTTP从本地IIS文件夹,或通过FTP或Microsoft FrontPage Extensions从远程网站(参见图2.2)。

图2.2 打开现有网站

接下来,您创建一个新的 Web 窗体,切换到设计视图,然后将“服务器/数据库资源管理器”窗口中的 Product 表拖到新的 Web 窗体上。这会在页面中添加一个 SqlDataSource 和一个 GridView 控件,然后您可以运行该页面查看结果。好吧,它不是很漂亮,可能包含您不想显示的列,但它确实为您节省了启动和运行页面基础功能的时间——而且您根本没有编写任何代码!(参见图 2.3)。

图2.3 在Visual Studio 2005中通过拖放创建数据显示页面

现在,您可以通过删除列、为值添加格式以及将预定义(自动格式)样式应用于GridView来微调页面,以提供您想要的功能。Visual Studio 2005和Visual Web Developer页面设计器为许多丰富的控件(例如GridView)提供了“任务”窗格,使完成所有这些任务变得容易。当您首次将控件添加到页面时,任务窗格会出现。您也可以通过单击将鼠标移到控件上时出现的小箭头图标来打开它(参见图2.4)。

图2.4 在Visual Studio和Visual Web Developer中打开任务窗格

任务窗格包含一组链接,这些链接会打开对话框或启动向导——具体取决于控件类型。对于GridView控件,正如您在图2.4中看到的,任务包括应用自动格式、选择适当的数据源控件、启用ASP.NET 2.0中新的GridView控件直接支持的各种功能,以及修改GridView控件显示的列。您只想显示六个最有用的列,因此可以从列表中删除其余列。此外,您希望StandardCostListPrice列显示为货币值,因此可以在这些列的DataFormatString属性中指定此值(参见图2.5)。

图2.5 修改GridView控件显示的列

启用行的排序和分页

现在GridView控件显示了数据库表中所需的列,但用户查找他们想要查看的行并不是很方便。所有行都以产品编号排序的一个长列表形式出现。如果用户能够以不同的顺序(也许在不知道产品编号时按名称)对行进行排序,那会很有帮助,并且能够将显示限制为特定数量的行并提供导航控件,以便他们可以看到单独的“页面”行也会很好。

在 ASP.NET 2.0 之前,您需要编写代码将源行集排序为所需顺序,然后将此代码与页面中的控件连接起来。在 ASP.NET 2.0 中,这一切都是自动的。您只需选中任务窗格中的复选框即可启用排序和分页(参见图 2.6)。列标题变为超链接,并且分页控件出现在网格底部。

图2.6 在GridView任务窗格中启用排序和分页

然后,您可以通过从任务窗格中出现的列表中选择一个合适的自动格式选项来美化页面,然后页面就完成了(参见图2.7)。

图2.7 将自动格式应用于GridView控件

您运行页面查看结果。点击任何一个列标题超链接都会按该列值以升序排序行。再次点击标题会更改排序顺序为降序。您已经创建了一个极其有用且易于使用的页面,并且您完全没有编写任何代码。

提供行编辑功能

当您打开GridView控件的任务窗格时,不妨利用它提供的其他一些功能。比如允许用户编辑行怎么样?即使在ASP.NET 1.x中,这通常也需要编写大量代码来处理作为网页中行编辑过程一部分的编辑/更新/取消选项,而且您仍然需要弄清楚如何通过执行SQL UPDATE语句将更改推回数据库。

在ASP.NET 2.0中,如果您乐意使用默认的参数化SQL语句方法来更新数据库表,所有这些都将消失。您只需在GridView控件的任务窗格中选择启用编辑启用删除选项。您将看到编辑删除链接出现在网格的左侧(参见图2.8)。

图2.8 在GridView控件的任务窗格中启用编辑

现在,用户可以编辑单个行中的任何列值(主键列除外),并将这些更改持久化到数据库中(参见图2.9),而您仍然没有编写一行代码!

图2.9 在GridView控件中编辑行

添加筛选以选择特定行集

正当您以为已经用一个闪亮的新网页来显示产品信息,满足了AdventureWorks Trading Inc.的CEO玛格丽特时,电话又响了。是AdventureWorks的销售经理迈克,他说他们公司不同部门的销售人员希望能够按类别筛选列表,而不仅仅是获得所有产品的列表。他还希望尽快实现这一功能。

午餐休息的美好想法烟消云散,你又回到了Visual Studio。你将需要某种控件,让用户可以选择他们想要查看的类别,最明显的就是一个下拉列表框(一个DropDownList控件)。你还需要某种方法来填充这个下拉列表,其中包含从产品表中的数据库行获取的可用类别。因此,第一步是将另一个SqlDataSource控件拖到页面上,然后点击任务窗格中的配置数据源链接以启动配置数据源向导。

向导的第一页指定要使用的连接字符串(您从列表中选择为前一个SqlDataSource控件创建的相同连接字符串),然后您可以指定查询以选择数据库中的行。名为ProductSubcategory的表包含Products表中每个项目的ID和名称(参见图2.10)。

图2.10 设置新SqlDataSource的属性以选择类别详细信息

现在您可以将DropDownList控件拖到页面上,并选择新的SqlDataSource控件作为数据源。您指定DropDownList将显示子类别名称,而列表中每个项目的值将是ProductSubcategoryID。此外,请务必将AutoPostback设置为True(在任务窗格中),以便所选值的更改将页面提交到服务器(参见图2.11)。

图2.11 设置新的DropDownList控件的属性

运行页面,您会看到一个类别列表。所有支持服务器端数据绑定的列表控件都可以以这种方式与数据源控件一起使用,即使是最初随ASP.NET 1.x版提供的DropDownList等控件。

剩下要做的就是将DropDownListGridView连接起来,以便GridView显示DropDownList中选定类别的行。为此您需要编写多少代码?也许您可以猜到答案是(仍然)不需要代码。

选择为GridView控件提供动力的SqlDataSource控件,然后通过在任务窗格中选择该选项再次运行“配置数据源向导”。在向导的第二页中,单击WHERE按钮以打开“添加WHERE子句”对话框。在这里,您指定条件将应用于的列;比较运算符;以及用于与列值进行比较的值的来源。这个值当然是DropDownList控件中当前选定的值,对话框会在添加按钮旁边显示将作为WHERE子句添加的SQL表达式(参见图2.12)。

图2.12 添加WHERE子句以按子类别进行选择

这会向SQL语句添加一个WHERE子句,其中包含一个用于类别的参数,并向SqlDataSource控件的声明中添加一个ControlParameter。如果您切换到Visual Studio 2005或Visual Web Developer中的视图,您将看到带有此ControlParameter元素嵌套在SelectParameters部分中的SqlDataSource控件的代码(参见清单2.1)。

清单2.1. SqlDataSource控件及其嵌套的ControlParameter

<asp:SqlDataSource ID="SqlDataSource1" runat="server" ... >
 <InsertParameters>
  ...
 </InsertParameters>
 <UpdateParameters>
  ...
 </UpdateParameters>
 <DeleteParameters>
  ...
 </DeleteParameters>
 <SelectParameters>
 <asp:ControlParameter ControlID="DropDownList1"
    Name="ProductSubcategoryID" 
      PropertyName="SelectedValue"
    Type="Int16" />
 </SelectParameters>
</asp:SqlDataSource>

现在,每次用户在DropDownList中做出选择时,页面都会回发,原始的SqlDataSource控件会使用DropDownListSelectedValue属性填充SQL语句中的参数,以便GridView只显示选定类别的行(参见图2.13)。

图2.13 使用DropDownList和ControlParameter按类别筛选行

以表单形式显示单行以进行编辑

现在页面显示数据库表中的行,允许它们按几乎任何顺序排序,并以单独的页面显示。它还允许对行应用产品类别筛选,并对除主键列以外的所有列执行编辑。然而,这种编辑功能并非最理想的方法,并且不如在单独的“表单”样式页面中编辑一行中的值的传统方法直观。

在ASP.NET 2.0中,您可以利用一个名为DetailsView的新控件,它提供了一个“每次一页”的数据源控件公开的行视图。此外,您可以将GridViewDetailsView控件连接起来,以便在网格中查看行很方便,而在“表单”视图中编辑更直观。

此过程的第一步是关闭GridView中的编辑功能,并启用选择,以便用户可以在GridView控件中选择一行。这两个任务只需通过在GridView控件的任务窗格中设置复选框即可完成(参见图2.14)。

图2.14 为GridView控件指定不带编辑功能的选择

现在,您将另一个SqlDataSource控件拖到页面上,然后单击任务窗格中的配置数据源链接以启动向导。在第一页中,您选择与之前相同的连接字符串。在向导的第二页中,您指定查询应包含Product表中除最后两列之外的所有列。然后单击WHERE按钮,像您在上一节中所做的那样,向SqlDataSource控件添加一个ControlParameter。但是,这次,指定GridView控件的SelectedValue属性,以便在回发之后,这个第三个SqlDataSource控件将仅公开在GridView控件中选择的行(参见图2.15)。

图2.15 为第三个SqlDataSource控件创建ControlParameter

默认情况下,SqlDataSource不提供行编辑功能。它只为主GridView控件提供SqlDataSource功能,因为您是通过将表从“服务器/数据库资源管理器”窗口拖到页面上创建的。当您从工具箱将SqlDataSource添加到页面时,您必须指定是否要能够更新行(在大多数情况下您不会,因此此默认值是合理的)。因此,请记住单击向导第二页中的高级按钮,并在出现的对话框中勾选选项(参见图2.16)。

图2.16 指定允许通过与此SqlDataSource关联的控件更新行的选项

接下来,将一个DetailsView控件拖到页面上,并使用任务窗格中的下拉选择数据源列表将其绑定到新的SqlDataSource控件。在此期间,使用DetailsView控件任务窗格中的选项,应用与之前相同的自动格式,并打开启用插入启用编辑启用删除。然后,您将看到编辑删除新建链接出现在控件底部(参见图2.17)。您还可以通过拖动右侧边框来调整DetailsView控件的宽度。

图2.17 设置DetailsView控件的编辑选项

现在您可以运行页面查看结果。您会发现,当您在GridView中选择行时,DetailsView会显示该行的值。此外,使用DetailsView底部的链接,所有值(主键除外)都可以进行编辑。您甚至可以插入新行。它看起来很像传统的执行数据访问应用程序,但您在不到一个小时内就构建了它——而且您仍然不需要编写任何代码(参见图2.18)!

图2.18 在链接的DetailsView控件中查看和编辑行

使用业务对象公开的数据

正当你靠在椅子上欣赏你的杰作时,电话又响了。这次是AdventureWorks Trading Inc.的高级开发人员——他一点也不高兴。他的团队花了几个月时间构建了一个面向对象的业务和数据访问层,他们不赞成人们直接使用SQL语句访问数据库。这种n层架构方法是一种常见场景,你一开始可能就应该更清楚。SqlDataSource可以使用存储过程而不是SQL语句,但要使用基于业务对象的数据层,则需要进行更重大的更改。

然而,您实际需要做的只是将公开数据的控件(SqlDataSource控件)更改为可以与业务对象通信的控件。AdventureWorks可以提供一个实现其数据访问层的.NET托管代码程序集,所以您所要做的就是改用它来代替直接的数据库访问。

然而,首先,您必须安装业务对象。由于它是一个.NET程序集,因此无需注册。一个编译好的DLL可以直接放到应用程序的bin文件夹中,然后在页面中引用。如果代码未编译会发生什么?在这种情况下,您可以从命令行运行编译器,或者使用Visual Studio编译它,然后部署。

更妙的是,在ASP.NET 2.0中,您可以部署源代码,并让ASP.NET在运行时将其编译并注册到应用程序。放置在应用程序根文件夹的App_Code子文件夹中的文件会在应用程序启动时(收到第一个请求时)自动编译,编译后的代码会存储在磁盘上,供后续请求使用。如果您编辑或更新源代码文件,它会自动重新编译,并且应用程序会重新启动。

AdventureWorks团队提供的(极其简化的)数据访问组件是一个名为DataLayer.cs的单个类文件,其中包含返回要在页面中显示的数据的公共方法(它不支持数据更新)。它公开的三个方法分别名为GetProductsByCategoryGetProductByProductIDGetCategoryList——如清单2.2所示。

清单2.2. 作为类文件实现的数据访问组件

using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
public class DataLayer
{
 public DataSet GetProductsByCategory(Int32 category)
 {
  String connect = ConfigurationManager.ConnectionStrings[
      "AdventureWorksConnectionString1"].ConnectionString;
  String sql = "SELECT ProductID, Name, ProductNumber, Color, "
        + "StandardCost, ListPrice, ProductSubcategoryID "
        + "FROM AdventureWorks.Production.Product "
        + "WHERE ProductSubcategoryID = @Category";
  using (SqlConnection con = new SqlConnection(connect))
  {
   SqlDataAdapter da = new SqlDataAdapter(sql, con);
   da.SelectCommand.Parameters.AddWithValue("@Category", category);
   DataSet ds = new DataSet();
   da.Fill(ds, "Products");
   return ds;
  }
 }
 public DataSet GetProductByProductID(Int32 pid)
 {
  String connect = ConfigurationManager.ConnectionStrings[
      "AdventureWorksConnectionString1"].ConnectionString;
  String sql = "SELECT ProductID, Name, ProductNumber, "
        + "SafetyStockLevel, Color, FinishedGoodsFlag, "
        + "MakeFlag, ReorderPoint, StandardCost, ListPrice, "
        + "Size, DaysToManufacture, Weight, "
        + "WeightUnitMeasureCode, SizeUnitMeasureCode, "
        + "ProductSubcategoryID, Style, Class, ProductLine, "
        + "ProductModelID, SellStartDate, SellEndDate, "
        + "DiscontinuedDate "
        + "FROM AdventureWorks.Production.Product "
        + "WHERE ProductID = @ProductID";
  using (SqlConnection con = new SqlConnection(connect))
  {
   SqlDataAdapter da = new SqlDataAdapter(sql, con);
   da.SelectCommand.Parameters.AddWithValue("@ProductID", pid);
   DataSet ds = new DataSet();
   da.Fill(ds, "Products");
   return ds;
  }
 }
 public SqlDataReader GetCategoryList()
 {
  String connect = ConfigurationManager.ConnectionStrings[
      "AdventureWorksConnectionString1"].ConnectionString;
  String sql = "SELECT ProductSubcategoryID, Name "
        + "FROM AdventureWorks.Production.ProductSubcategory";
  SqlConnection con = new SqlConnection(connect);
  try
  {
   con.Open();
   SqlCommand cmd = new SqlCommand(sql, con);
   return cmd.ExecuteReader(CommandBehavior.CloseConnection);
  }
  catch
  {
   return null;
  }
 }
}

- 此处列出的数据访问类仅旨在作为使用ObjectDataSource控件的基本演示。“实际”示例通常会包含更多代码,包含更新方法,并使用存储过程而不是声明性SQL语句。


ASP.NET页面通过数据源控件调用这些方法,从数据库表中获取行。因此,部署数据访问类文件后的下一步是,从页面中删除SqlDataSource控件,并用ObjectDataSouce控件实例替换它们。对于每个控件,使用配置数据源向导将这些控件连接到数据访问层,以便它们可以公开与SqlDataSource控件相同的行集。无需更改页面的UI,并且除了数据访问层类之外,仍然不需要任何代码!

图2.19显示了将填充类别DropDownListObjectDataSource连接到GetCategoryList方法所需的仅有的两个步骤,因为此方法不接受任何参数。GridView控件的ObjectDataSource需要一个参数,这在配置数据源向导的第三步中指定——它识别出需要一个参数,并且您将其链接到DropDownListSelectedValue属性,就像您之前使用SqlDataSource控件时所做的那样(参见图2.20)。

图2.19 配置DropDownList的ObjectDataSource

图2.20 配置GridView的ObjectDataSource

在添加了第三个ObjectDataSource控件来替换填充DetailsView控件的SqlDataSource之后,您只需使用每个控件的任务窗格将DropDownListGridViewDetailsView控件连接到新的数据源控件。由于数据层不支持编辑,因此任务窗格不会显示启用编辑复选框(参见图2.21)。

图2.21 将数据显示控件连接到ObjectDataSource实例

现在您可以运行该页面,并且会看到——除了编辑功能之外——结果是相同的(参见图2.22)。这正是您想要和期望的,因为UI没有改变。此外,从声明性SQL语句更改为数据访问/业务对象层的工作并不困难或耗时。

图2.22 使用数据访问/业务逻辑层的结果

缓存数据以减少数据库访问

为AdventureWorks Trading Inc.的玛格丽特构建新页面花了两小时,你准备休息一下。然而,露西(数据库管理员)刚刚得知应用程序中的新功能。她的工作是保持数据库平稳高效运行,她担心你会拖慢速度。随着用户对行进行排序、分页、筛选、选择和编辑,每个回发都会对她的数据库服务器造成持续的冲击。

露西非常相信对不经常更改的数据进行缓存,并希望您在新页面中实现此功能。不,不是下周,而是现在。看来你计划的高尔夫比赛今天泡汤了。

AdventureWorks Trading Inc.使用新的SQL Server 2005数据库,因此您可以利用一个名为数据库缓存失效的功能来提高性能并减少数据库服务器负载。这比基于数据多久可能更改的最佳猜测来缓存特定时间段的传统技术更有意义。

ASP.NET数据库缓存失效支持SQL Server 2000和SQL Server 2005。在SQL Server 2000中,您使用名为aspnet_regsql的特殊工具(位于您机器的%windir%\Microsoft.NET\Framework\[版本]文件夹中)来准备数据库和包含源数据的表。您还需要编辑您的Web.Config文件(有关更多详细信息,请参见第11章)。

在SQL Server 2005中,数据库缓存失效依赖于数据库的Broker Service功能。这允许SqlCacheDependency链接到数据源控件,以便数据在ASP.NET中缓存,并且仅在数据更改时(或数据库服务器上发生其他可通知事件(例如服务器重启)时)才从数据库刷新。

使用数据源控件时,只需向页面添加一个包含SqlDependency属性的OutputCache指令即可。

<%@OutputCache SqlDependency="CommandNotification"
        Duration="60" VaryByParam="*" %>

注意 - 请注意,在使用命令通知架构之前,您必须为数据库启用Broker Service,并授予相关权限。有关更多详细信息,请参阅MSDN


现在您可以运行页面,然后刷新它而不会导致数据库查询发生(您可以使用SQL Server附带的SQL Profiler工具监视数据库活动)。但是,如果您在Visual Studio或Visual Web Developer中打开源表并更改其中一个列值,您会发现下次刷新页面时会命中数据库。

使用母版页以提供一致的外观和感觉

您使用“自动格式”功能应用于GridViewDetailsView控件的样式,提供了一个相当吸引人的结果。然而,俗话说“情人眼里出西施”,所以再次听到电话铃响也就不足为奇了。这次,市场部的胡安-保罗“只是打电话来说”他们已经有了网站的企业设计方案,他非常希望您能帮助“促进外观兼容性,以通过熟悉基础设施来提高员工资源利用率”。

你胡乱猜测他的意思是他希望新页面遵循现有页面的相同样式和布局。在向胡安-保罗承诺你将“亲自努力突破界限,推动流程,并向着令人满意且视觉上连贯的解决方案迈进”之后,你再次启动Visual Studio。

幸运的是,您在构建AdventureWorks网站时利用了ASP.NET 2.0的母版页功能。因此,将新页面融入现有网站只需将其从“普通”网页转换为内容页并引用母版页文件即可。您这样做是因为您意识到市场部门对生活抱有善变的态度,未来某个时候可能需要更改网站的整体设计和布局。图2.23显示了母版页,其中ContentPlaceHolder控件指示了每个内容页内容所占据的区域。创建此页面的代码如清单2.3所示,您可以看到HTML表中的PlaceHolder控件。

图2.23 Visual Studio中AdventureWorks母版页的设计视图

清单2.3. AdventureWorks母版页的源代码

<%@ Master Language="C#" AutoEventWireup="true"
  CodeFile="MasterPage.master.cs" Inherits="MasterPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
     "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
  <title>AdventureWorks Inc.</title>
  <link rel="Stylesheet" type="text/css"
     href="StyleSheet.css" title="Default" />
</head>
<body topmargin="0" leftmargin="0" rightmargin="0">
 <form id="form1" runat="server">
 <table width="100%" border="0" cellpadding="0" cellspacing="0">
  <tr>
  <td align="left" colspan="3" bgcolor="#000000">
   <img src="Images/header.jpg" border="0" vspace="0" />
  </td>
  </tr>
  <tr>
  <td bgcolor="#000000">&nbsp;</td>
  <td style="padding:10px">
   <asp:ContentPlaceholder id="CP1" runat="server" />
  </td>
  <td bgcolor="#000000">&nbsp;</td>
  </tr>
  <tr>
  <td align="center" colspan="3" bgcolor="#000000">
   <span class="footer">
   AdventureWorks Inc. is a fictional corporation.
   </span>
  </td>
  </tr>
 </table>
 </form>
</body>
</html>

所需要的只是从页面中删除所有不属于新网页行显示的

和其他元素。然后将MasterPageFile属性添加到Page指令中,并将内容包装在Content控件中,该控件指定它将填充母版页上的ContentPlaceHolder控件。清单2.4显示了其大致结构。

清单2.4. 内容页的概要结构

<%@ Page Language="C#" AutoEventWireup="true"
     CodeFile="Products.aspx.cs" Inherits="Products"
    MasterPageFile="~/MasterPage.master" %>
<asp:Content ContentPlaceHolderID="CP1" runat="server" ID="Content1">
 ... all page content goes here ...
</asp:Content>

现在,在“产品列表”页面的设计视图中,您可以看到新页面如何融入母版页(参见图2.24),母版页本身呈灰色,除非您在单独的窗口中打开它,否则无法编辑。在运行时,母版页内容与您正在构建的新页面生成的内容合并,从而产生组合结果。

图2.24 新页面在母版页中运行

添加菜单及其他导航功能

网站缺少的一个项目是便于在页面之间导航的菜单。同样,ASP.NET 2.0提供了实现各种导航策略所需的一切,而常见且有效的解决方案通常是动态弹出式或下拉式菜单。驱动Menu控件的数据来自名为Web.sitemap的XML文件,该文件定义了菜单的项目、它们在分层菜单结构中的位置、每个项目的弹出工具提示以及导航的目标URL。将新的“产品”页面添加到XML文件后,菜单将自动提供指向该页面的链接。

您从工具箱中拖动一个SiteMapDataSource控件并将其放到页面上,使用“配置数据源向导”选择Web.sitemap文件。然后,您从工具箱中拖动一个Menu控件并将其放到母版页上,在选择数据源列表中选择新的SiteMapDataSource控件,并使用任务窗格应用合适的自动格式(参见图2.25)。

图2.25 向母版页添加SiteMapDataSource和菜单控件

您还决定通过在母版页的右侧部分的底部,即ContentPlaceHolder控件下方,添加一个SiteMapPath控件,让用户更容易知道他们在网站层次结构中的位置。它使用相同的Web.sitemap文件,并自动显示当前页面的“面包屑导航”(参见图2.26)。此外,就像您目前使用的ASP.NET 2.0的所有其他功能一样,无需编写任何代码!一切都正常运行……

图2.26 向母版页添加菜单和导航路径

摘要

尽管这是一个有些牵强的场景,但本章已经演示了ASP.NET 2.0的强大功能,以及它如何大大缩短开发时间,同时帮助您构建高效且美观的网站和Web应用程序。ASP.NET 2.0的主要目标之一是进一步减少您编写代码来构建动态交互式页面所需的代码量,特别是消除了几乎所有项目都需要的重复代码!正如您从本章中看到的那样,您可以在不编写任何代码的情况下取得显著的成果。

在本章中,您已经了解了如何创建和演进数据访问页面,从将数据库表拖到编辑窗口开始。然后您看到了更改网格内容和外观以及添加排序、分页和编辑等功能是多么容易。下一阶段增加了类别选择功能,以便只显示特定行集。之后是实现“表单”样式的数据视图。

一旦页面提供了所需的功能,接下来您将看到如何通过使用母版页匹配整体样式和布局,以及将其与菜单和导航系统集成,使其成为现有网站的一部分。所有这些都在可视化设计工具中完成,使用拖放技术和向导,并且完全没有编写任何代码。

在下一章中,您将更深入地研究此处介绍的数据源控件和数据显示控件,了解它们如何提供广泛的功能来支持各种数据管理需求。

© Pearson Education 版权所有。保留所有权利。

© . All rights reserved.