使用母版页创建站点范围内布局 (C#)

作者 :斯科特·米切尔

下载 PDF

本教程将显示母版页基础知识。 也就是说,什么是母版页、如何创建母版页、什么是内容位置持有者、如何创建使用母版页的 ASP.NET 页、如何修改母版页自动反映在其关联的内容页中,等等。

介绍

设计良好的网站的一个属性是一致的网站范围页面布局。 例如,获取 www.asp.net 网站。 撰写本文时,每一页在页面顶部和底部具有相同的内容。 如图 1 所示,每页顶部显示一个灰色条形图,其中包含Microsoft社区列表。 下面是网站徽标、网站翻译到的语言列表以及核心部分:主页、入门、学习、下载等。 同样,页面底部包括有关 www.asp.net 广告、版权声明和隐私声明链接的信息。

www.asp.net 网站在所有页面中都采用一致的外观

图 01:www.asp.net 网站在所有页面中采用一致的外观(单击可查看全尺寸图像

设计良好的网站的另一个属性是可以轻松更改网站的外观。 图 1 显示了 截至 2008 年 3 月 www.asp.net 主页,但在现在和本教程的发布之间,外观可能已更改。 也许顶部的菜单项将展开,以包含 MVC 框架的新部分。 或者,可能会推出具有不同颜色、字体和布局的全新设计。 将此类更改应用于整个网站应该是一个快速而简单的过程,不需要修改构成网站的数千个网页。

通过使用 母版页,可以在 ASP.NET 中创建网站范围的页面模板。 简言之,母版页是一种特殊类型的 ASP.NET 页面,用于定义所有 内容页 中通用的标记,以及可逐页自定义的内容页的区域。 (内容页是绑定到母版页的 ASP.NET 页。每当母版页的布局或格式更改时,其所有内容页的输出同样会立即更新,这使得应用网站范围的外观更改与更新和部署单个文件(即母版页)一样简单。

这是探索使用母版页的一系列教程中的第一个教程。 在本教程系列教程中,我们将:

  • 检查创建母版页及其关联的内容页,
  • 讨论各种提示、技巧和陷阱,
  • 确定常见的母版页缺陷并探索解决方法,
  • 了解如何从内容页访问母版页,反之亦然,
  • 了解如何在运行时指定内容页的母版页,以及
  • 其他高级母版页主题。

这些教程旨在简洁明了,提供了大量屏幕截图的分步说明,让你直观地完成该过程。 每个教程在 C# 和 Visual Basic 版本中都可用,并包括下载使用的完整代码。

本就职教程从母版页基础知识开始。 我们将讨论母版页的工作原理、了解如何使用 Visual Web 开发人员创建母版页和关联内容页,并查看母版页的更改如何立即反映在其内容页中。 现在就开始吧!

了解母版页的工作原理

构建具有一致网站范围页面布局的网站需要每个网页除了发出自定义内容之外,还会发出通用格式标记。 例如,虽然每个教程或论坛文章 www.asp.net 都有自己的唯一内容,但这些页面还呈现一系列常见 <div> 元素,这些元素显示顶级部分链接:主页、入门、学习等。

有多种技术可用于创建外观一致的网页。 一种天真的方法是将通用布局标记复制并粘贴到所有网页中,但此方法有许多缺点。 对于初学者,每次创建新页面时,都必须记住将共享内容复制并粘贴到页面中。 此类复制和粘贴操作已成熟,出现错误,因为可能会意外地将共享标记的子集复制到新页面中。 为了弥补这一点,这种方法使现有的网站范围外观替换为一个新的痛苦,因为必须编辑网站中的每个页面才能使用新的外观。

ASP.NET 版本 2.0 之前,页面开发人员通常会将常用标记放在用户控件,然后将这些用户控件添加到每个页面。 此方法要求页面开发人员记住将用户控件手动添加到每个新页面,但允许更轻松地进行网站范围的修改,因为在更新通用标记时,只需要修改用户控件。 遗憾的是,Visual Studio .NET 2002 和 2003 (用于创建 ASP.NET 1.x 应用程序的 Visual Studio 版本)在设计视图中呈现为灰色框的用户控件。 因此,使用此方法的页面开发人员不喜欢 WYSIWYG 设计时环境。

ASP.NET 版本 2.0 和 Visual Studio 2005 中介绍了使用用户控件的缺点,并引入了 母版页。 母版页是一种特殊类型的 ASP.NET 页面,用于定义网站范围的标记和关联内容页定义其自定义标记的区域。 如步骤 1 中所示,这些区域由 ContentPlaceHolder 控件定义。 ContentPlaceHolder 控件只是表示母版页控件层次结构中的一个位置,其中自定义内容可由内容页注入。

注意

自 ASP.NET 版本 2.0 以来,母版页的核心概念和功能没有变化。 但是,Visual Studio 2008 为嵌套母版页提供设计时支持,这是 Visual Studio 2005 中缺少的功能。 我们将在将来的教程中了解如何使用嵌套母版页。

图 2 显示了 www.asp.net 母版页的外观。 请注意,母版页定义通用网站范围的布局-每个页面的顶部、底部和右侧的标记,以及位于左侧的 ContentPlaceHolder,每个网页的唯一内容位于该位置。

母版页基于内容页定义网站范围的布局和区域可编辑

图 02:母版页基于内容页定义网站范围的布局和可编辑的区域

定义母版页后,可以通过复选框的刻度绑定到新的 ASP.NET 页。 这些 ASP.NET 页(称为内容页)包括每个母版页的 ContentPlaceHolder 控件的内容控件。 当通过浏览器访问内容页时,ASP.NET 引擎将创建母版页的控件层次结构,并将内容页的控件层次结构注入适当的位置。 此组合控件层次结构呈现,生成的 HTML 将返回到最终用户的浏览器。 因此,内容页将发出在 ContentPlaceHolder 控件外部的母版页中定义的通用标记,以及在其自己的内容控件中定义的特定于页面的标记。 图 3 说明了此概念。

请求页的标记融合到母版页中

图 03:请求的页面标记融合到母版页中(单击可查看全尺寸图像

现在,我们已经讨论了母版页的工作原理,让我们看看如何使用 Visual Web Developer 创建母版页和关联的内容页。

注意

为了达到尽可能广泛的受众,我们将使用 ASP.NET 3.5 和 Microsoft 免费版本的 Visual Studio 2008 Visual Web Developer 2008(Visual Web Developer 2008)创建我们在整个教程系列中构建的 ASP.NET 网站。 如果尚未升级到 ASP.NET 3.5,请不要担心 - 这些教程中讨论的概念同样适用于 ASP.NET 2.0 和 Visual Studio 2005。 但是,某些演示应用程序可能会使用 .NET Framework 版本 3.5 的新增功能;使用 3.5 特定功能时,我包括一个说明,讨论如何在版本 2.0 中实现类似的功能。 请记住,可从每个教程下载的演示应用程序面向 .NET Framework 版本 3.5,这会导致包含 Web.config 3.5 个特定配置元素的文件以及对 ASP.NET 页面代码隐藏类中语句中 using 3.5 特定命名空间的引用。 长篇短文,如果尚未在计算机上安装 .NET 3.5,则无需先从 Web.config中删除 3.5 特定标记,可下载的 Web 应用程序将无法正常工作。 有关本主题的详细信息,请参阅 Web.config “文件 ”。 还需要删除 using 引用 3.5 特定命名空间的语句。

步骤 1:创建母版页

在探索创建和使用母版页和内容页面之前,首先需要一个 ASP.NET 网站。 首先,创建新的基于文件系统的 ASP.NET 网站。 为此,请启动 Visual Web 开发人员,然后转到“文件”菜单并选择“新建网站”,显示“新建网站”对话框(请参阅图 4)。 选择 ASP.NET 网站模板,将“位置”下拉列表设置为文件系统,选择要放置网站的文件夹,并将语言设置为 C# 。 这将创建一个包含 Default.aspx ASP.NET 页、 App_Data 文件夹和 Web.config 文件的新网站。

注意

Visual Studio 支持两种项目管理模式:网站项目和 Web 应用程序项目。 网站项目缺少项目文件,而 Web 应用程序项目模仿 Visual Studio .NET 2002/2003 中的项目体系结构 - 它们包括项目文件,并将项目的源代码编译为位于文件夹中的 /bin 单个程序集。 Visual Studio 2005 最初仅支持网站项目,尽管 Web 应用程序项目模型是使用 Service Pack 1 重新引入的;Visual Studio 2008 提供这两个项目模型。 但是,Visual Web Developer 2005 和 2008 版本仅支持网站项目。 在本系列教程中,我使用网站项目模型进行演示。 如果你使用的是非 Express 版本,并且想要改用 Web 应用程序项目模型,可以随意执行此操作,但请注意,屏幕上看到的内容与必须采取的步骤与这些教程中提供的说明之间存在一些差异。

创建新的基于文件系统的网站

图 04:创建新的基于文件系统的网站(单击以查看全尺寸图像

接下来,右键单击项目名称,选择“添加新项”,然后选择“母版页”模板,将母版页添加到根目录中的网站。 请注意,母版页以扩展名 .master结尾。 将此新母版页 Site.master 命名,然后单击“添加”。

将名为 Site.master 的母版页添加到网站

图 05:添加名为 Site.master 网站的母版页(单击可查看全尺寸图像

通过 Visual Web Developer 添加新母版页文件会使用以下声明性标记创建母版页:

<%@ 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>Untitled Page</title>
 <asp:ContentPlaceHolder id="head" runat="server">
 </asp:ContentPlaceHolder>
</head>
<body>
 <form id="form1" runat="server">
 <div>
 <asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server">
 
 </asp:ContentPlaceHolder>
 </div>
 </form>
</body>
</html>

声明性标记中的第一行是 @Master 指令。 该 @Master 指令类似于 @Page ASP.NET 页中显示的指令 。 它定义服务器端语言(C#),以及有关母版页代码隐藏类的位置和继承的信息。

DOCTYPE 页面的声明性标记显示在指令下方 @Master 。 该页包含静态 HTML 以及四个服务器端控件:

  • Web 窗体 (the <form runat="server"> - 因为所有 ASP.NET 页通常都有 Web 窗体 - 并且母版页可能包含必须在 Web 窗体中显示的 Web 控件 - 请务必将 Web 窗体添加到母版页(而不是将 Web 窗体添加到每个内容页)。
  • 名为 ContentPlaceHolder1 - 此 ContentPlaceHolder 控件显示在 Web 窗体中,并充当内容页用户界面的区域。
  • 服务器端<head>元素 - <head> 该元素具有属性runat="server",因此可通过服务器端代码访问该元素。 以 <head> 这种方式实现该元素,以便以编程方式添加或调整页面的标题和其他 <head>相关标记。 例如,设置 ASP.NET 页 Title 的属性会更改 <title> 服务器控件呈现的 <head> 元素。
  • 名为 ContentPlaceHolder 控件的 head ContentPlaceHolder 控件显示在服务器控件中 <head> ,可用于以声明方式向元素添加内容 <head>

此默认母版页声明性标记用作设计自己的母版页的起点。 随时编辑 HTML 或向母版页添加其他 Web 控件或 ContentPlaceHolders。

注意

设计母版页时,请确保母版页包含 Web 窗体,并且至少有一个 ContentPlaceHolder 控件出现在此 Web 窗体中。

创建简单的网站布局

让我们展开 Site.master默认声明性标记以创建网站布局,其中所有页面共享:通用标题;左侧列包含导航、新闻和其他网站范围内容;以及显示“由Microsoft ASP.NET 提供支持”图标的页脚。 图 6 显示通过浏览器查看其内容页之一时母版页的最终结果。 图 6 中的红色圆圈区域特定于所访问的页面(Default.aspx);其他内容在母版页中定义,因此在所有内容页面中保持一致。

母版页定义顶部、左侧和底部部分的标记

图 06:母版页定义顶部、左侧和底部部分的标记(单击可查看全尺寸图像

若要实现图 6 中显示的网站布局,请首先更新 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>Untitled Page</title>
 <asp:ContentPlaceHolder id="head" runat="server">
 </asp:ContentPlaceHolder>
 <link href="Styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
 <form id="form1" runat="server">
 <div id="topContent">
 <a href="Default.aspx">Master Pages Tutorials</a>
 </div>
 
 <div id="mainContent">
 <asp:ContentPlaceHolder id="MainContent" runat="server">
 </asp:ContentPlaceHolder>
 </div>
 
 <div id="leftContent">
 <h3>Lessons</h3>    
 <ul>
 <li>TODO</li>
 </ul>
 <h3>News</h3>    
 <ul>
 <li>TODO</li>
 </ul>
 </div>
 
 <div id="footerContent">
 <img src="Images/PoweredByASPNET.gif" alt="Powered by ASP.NET!" />
 </div>
 </form>
</body>
</html>

母版页的布局是使用一系列 <div> HTML 元素定义的。 包含topContent<div>显示在每个页面顶部的标记,而 mainContentleftContentfooterContent <div> s 分别用于显示页面的内容、左列和“由Microsoft ASP.NET 提供支持”图标。 除了添加这些 <div> 元素,我还将 ID 主 ContentPlaceHolder 控件的属性重命名为 < ContentPlaceHolder1 a0 MainContent/>。

这些分类<div>元素的格式和布局规则在级联样式表 (CSS) 文件中Styles.css进行拼写,该文件是通过<母版页<头>元素中的链接>元素指定的。 这些各种规则定义上述每个 <div> 元素的外观。 例如,topContent<div>该元素显示“母版页教程”文本和链接,其格式规则指定Styles.css如下:

#topContent {
 text-align: right;
 background-color: #600;
 color: White;
 font-size: x-large;
 text-decoration: none;
 font-weight: bold;
 padding: 10px;
 height: 50px;
}

如果你在计算机中关注,则需要下载本教程随附的代码,并将 Styles.css 该文件添加到项目中。 同样,还需要创建一个名为 Images 的文件夹,并将下载的演示网站中的“由Microsoft ASP.NET 提供支持”图标复制到项目。

注意

有关 CSS 和网页格式的讨论超出了本文的范围。 有关 CSS 的详细信息,请查看 W3Schools.comCSS 教程。 我还鼓励你下载本教程随附的代码并播放 CSS 设置, Styles.css 以查看不同格式规则的效果。

使用现有设计模板创建母版页

多年来,我为中小企业建立了许多 ASP.NET Web 应用程序。 我的一些客户端具有他们要使用的现有网站布局;其他人雇佣了一位称职的图形设计师。 有几个委托我设计网站布局。 正如图 6 所示,让程序员设计网站布局的任务通常与让会计师在医生纳税时进行开放心脏手术一样明智。

幸运的是,有无数网站提供免费的 HTML 设计模板 - 谷歌为搜索词“免费网站模板”返回了 600 多万个结果。我最喜欢的一个是 OpenDesigns.org。找到喜欢的网站模板后,将 CSS 文件和图像添加到网站项目,并将模板的 HTML 集成到母版页中。

注意

Microsoft还提供许多 免费的 ASP.NET 设计启动工具包模板,这些模板 集成到 Visual Studio 中的“新建网站”对话框中。

步骤 2:创建关联的内容页

创建母版页后,便可以开始创建绑定到母版页的 ASP.NET 页。 此类页面称为 内容页

让我们向项目添加新 ASP.NET 页,并将其 Site.master 绑定到母版页。 右键单击解决方案资源管理器中的项目名称,然后选择“添加新项”选项。 选择 Web 表单模板,输入名称 About.aspx,然后选中“选择母版页”复选框,如图 7 所示。 这样做将显示“选择母版页”对话框(请参阅图 8),可从中选择要使用的母版页。

注意

如果使用 Web 应用程序项目模型而不是网站项目模型创建了 ASP.NET 网站,则不会在图 7 中显示的“添加新项”对话框中看到“选择母版页”复选框。 若要在使用 Web 应用程序项目模型时创建内容页,必须选择 Web 内容表单模板而不是 Web 表单模板。 选择 Web 内容表单模板并单击“添加”后,将显示图 8 中显示的“选择母版页”对话框。

添加新内容页

图 07:添加新内容页(单击以查看全尺寸图像

选择 Site.master 母版页

图 08:选择 Site.master 母版页(单击可查看全尺寸图像

如以下声明性标记所示,新内容页包含一个 @Page 指令,该指令指向其母版页和每个母版页的 ContentPlaceHolder 控件的内容控件。

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

注意

在步骤 1 的“创建简单网站布局”部分中,我重命名为 ContentPlaceHolder1 MainContent。 如果未以相同方式重命名此 ContentPlaceHolder 控件 ID ,则内容页的声明性标记与上面所示的标记略有不同。 也就是说,第二个内容控件 ContentPlaceHolderID 将反映 ID 母版页中相应的 ContentPlaceHolder 控件。

呈现内容页时,ASP.NET 引擎必须将页面的内容控件与其母版页的 ContentPlaceHolder 控件融合在一起。 ASP.NET 引擎根据 @Page 指令的属性确定内容页的 MasterPageFile 母版页。 如上述标记所示,此内容页绑定到 ~/Site.master

因为母版页有两个 ContentPlaceHolder 控件, headMainContent Visual Web 开发人员生成了两个内容控件。 每个内容控件通过其 ContentPlaceHolderID 属性引用特定的 ContentPlaceHolder。

母版页在以前的网站范围模板技术上大放异彩,其设计时支持。 图 9 显示了 About.aspx 通过 Visual Web 开发人员的设计视图查看的内容页面。 请注意,虽然母版页内容可见,但它灰显且无法修改。 但是,与母版页的 ContentPlaceHolders 对应的内容控件是可编辑的。 与任何其他 ASP.NET 页面一样,可以通过通过源视图或设计视图添加 Web 控件来创建内容页面的界面。

内容页的设计视图同时显示特定于页面的内容和母版页内容

图 09:内容页的设计视图同时显示特定于页面的内容和母版页内容(单击可查看全尺寸图像

将标记和 Web 控件添加到内容页

花点时间为 About.aspx 页面创建一些内容。 如图 10 所示,我输入了“关于作者”标题和几段文本,但也可以随意添加 Web 控件。 创建此接口后,通过浏览器访问 About.aspx 页面。

通过浏览器访问About.aspx页

图 10:通过浏览器访问 About.aspx 页面(单击以查看全尺寸图像

请务必了解,请求的内容页及其关联的母版页完全融合在 Web 服务器上并呈现为一个整体。 然后,最终用户的浏览器将发送生成的融合 HTML。 若要验证这一点,请通过转到“视图”菜单并选择“源”来查看浏览器收到的 HTML。 请注意,没有框架或任何其他专用技术用于在单个窗口中显示两个不同的网页。

将母版页绑定到现有 ASP.NET 页

正如我们在此步骤中看到的那样,将新内容页添加到 ASP.NET Web 应用程序就像选中“选择母版页”复选框并选取母版页一样简单。 遗憾的是,将现有 ASP.NET 页转换为母版页并不容易。

若要将母版页绑定到现有 ASP.NET 页,需要执行以下步骤:

  1. MasterPageFile 属性添加到 ASP.NET 页的 @Page 指令,并将其指向相应的母版页。
  2. 为母版页中的每个 ContentPlaceHolders 添加内容控件。
  3. 选择性地剪切 ASP.NET 页的现有内容并将其粘贴到相应的内容控件中。 我在此处“有选择地”说,因为 ASP.NET 页面可能包含已由母版页(如 DOCTYPE<html> 元素和 Web 窗体)表示的标记。

有关此过程的分步说明以及屏幕截图,请查看 Scott Guthrie“使用母版页”和“网站导航 ”教程。 “更新 Default.aspx 和使用 DataSample.aspx 母版页”部分详细介绍了这些步骤。

由于创建新内容页面比将现有 ASP.NET 页面转换为内容页要容易得多,因此建议每当创建新的 ASP.NET 网站向网站添加母版页时。 将所有新的 ASP.NET 页绑定到此母版页。 如果初始母版页非常简单或简单,请不要担心;稍后可以更新母版页。

注意

创建新的 ASP.NET 应用程序时,Visual Web 开发人员会添加一个 Default.aspx 未绑定到母版页的页面。 如果要练习将现有 ASP.NET 页转换为内容页,请继续操作 Default.aspx。 或者,可以删除 Default.aspx 然后重新添加它,但这次选中“选择母版页”复选框。

步骤 3:更新母版页的标记

母版页的主要优点之一是,单个母版页可用于为网站上的许多页面定义整体布局。 因此,更新网站的外观需要更新单个文件 - 母版页。

为了说明此行为,让我们更新母版页,将当前日期包含在左列顶部。 添加一个名为 DateDisplay> 的leftContent<div>标签。

<div id="leftContent">
 <p>
 <asp:Label ID="DateDisplay" runat="server"></asp:Label>
 </p>
 
 <h3>Lessons</h3>    
 <ul>
 <li>TODO</li>
 </ul>
 <h3>News</h3>    
 <ul>
 <li>TODO</li>
 </ul>
</div>

接下来,为母版页创建 Page_Load 事件处理程序并添加以下代码:

protected void Page_Load(object sender, EventArgs e)
{
    DateDisplay.Text = DateTime.Now.ToString("dddd, MMMM dd");
}

上面的代码将 Label Text 的属性设置为格式为星期几的当前日期和时间、月份的名称和两位数的日期(请参阅图 11)。 通过此更改,重新访问其中一个内容页面。 如图 11 所示,生成的标记会立即更新,以包括对母版页所做的更改。

查看内容页时反映母版页的更改

图 11:查看内容页时反映母版页的更改(单击以查看全尺寸图像

注意

如本示例所示,母版页可能包含服务器端 Web 控件、代码和事件处理程序。

总结

母版页使 ASP.NET 开发人员能够设计易于更新的一致的网站范围布局。 创建母版页及其关联的内容页与创建标准 ASP.NET 页面一样简单,因为 Visual Web 开发人员提供了丰富的设计时支持。

在本教程中创建的母版页示例有两个 ContentPlaceHolder 控件, head 以及 MainContent。 但是,我们只在内容页中为 MainContent ContentPlaceHolder 控件指定了标记。 在下一教程中,我们将了解如何在内容页中使用多个内容控件。 我们还了解如何为母版页中的内容控件定义默认标记,以及如何使用母版页中定义的默认标记以及从内容页提供自定义标记之间进行切换。

快乐编程!

深入阅读

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

关于作者

斯科特·米切尔是多个 ASP/ASP.NET 书籍的作者,4GuysFromRolla.com 的创始人,自1998年以来一直在与Microsoft Web 技术合作。 斯科特担任独立顾问、教练和作家。 他的最新书是 山姆斯在24小时内 ASP.NET 3.5。 斯科特可以在他的博客上 mitchell@4GuysFromRolla.com 或通过他的博客联系 http://ScottOnWriting.NET

特别感谢

有兴趣查看即将发布的 MSDN 文章? 如果是这样,请把我扔一条线。mitchell@4GuysFromRolla.com