以编程方式指定母版页 (VB)

作者 :斯科特·米切尔

查看通过 PreInit 事件处理程序以编程方式设置内容页的母版页。

简介

由于“使用母版页创建网站范围布局”中的首例示例,所有内容页都通过MasterPageFile指令中的@Page属性以声明方式引用了母版页。 例如,以下 @Page 指令将内容页链接到母版页 Site.master

<%@ Page Language="C#" MasterPageFile="~/Site.master"... %>

命名空间中的System.Web.UI包括一个MasterPageFile属性,该属性返回内容页母版页的路径;它是由指令设置的属性@PagePage 此属性还可用于以编程方式指定内容页的母版页。 如果要根据外部因素(例如访问页面的用户)动态分配母版页,此方法非常有用。

在本教程中,我们将第二个母版页添加到网站,并动态确定在运行时要使用的母版页。

步骤 1:查看页面生命周期

每当请求到达 Web 服务器以获取内容页的 ASP.NET 页面时,ASP.NET 引擎必须将页面的内容控件融合到母版页的相应 ContentPlaceHolder 控件中。 此融合创建一个控件层次结构,然后可以继续执行典型的页面生命周期。

图 1 说明了这种融合。 图 1 中的步骤 1 显示了初始内容和母版页控件层次结构。 在 PreInit 阶段的尾端,页面中的内容控件将添加到母版页中的相应 ContentPlaceHolders(步骤 2)。 在此融合之后,母版页充当融合控件层次结构的根。 然后将此融合控件层次结构添加到页面中,以生成最终的控制层次结构(步骤 3)。 净结果是页面的控件层次结构包括融合控件层次结构。

母版页和内容页的控件层次结构在 PreInit 阶段合并在一起

图 01:母版页和内容页的控件层次结构在 PreInit 阶段合并在一起(单击可查看全尺寸图像

步骤 2:从代码设置MasterPageFile属性

此融合中的母版页部件取决于对象的MasterPageFile属性的值PageMasterPageFile@Page指令中设置属性具有在初始化阶段分配 Page's MasterPageFile 属性的净效果,这是页面生命周期的第一个阶段。 或者,我们可以以编程方式设置此属性。 但是,必须在图 1 中的融合之前设置此属性。

在 PreInit 阶段开始时, Page 对象将引发其 PreInit 事件 并调用其 OnPreInit 方法。 若要以编程方式设置母版页,我们可以为 PreInit 事件创建事件处理程序或重写 OnPreInit 方法。 让我们看看这两种方法。

首先 Default.aspx.vb,打开网站主页的代码隐藏类文件。 通过键入以下代码为页面 PreInit 的事件添加事件处理程序:

Protected Sub Page_PreInit(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreInit 
End Sub

在这里,我们可以设置属性 MasterPageFile 。 更新代码,以便将值“~/Site.master”分配给 MasterPageFile 属性。

Protected Sub Page_PreInit(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreInit 
 Me.MasterPageFile = "~/Site.master"
End Sub

如果设置断点并开始调试,你将看到每当 Default.aspx 访问页面或每当有回发到此页面时, Page_PreInit 事件处理程序将执行 MasterPageFile 该属性,并将该属性分配给“~/Site.master”。

或者,可以重写 PageOnPreInit 的方法,并在其中设置 MasterPageFile 属性。 在此示例中,我们不要在特定页面中设置母版页,而是从 BasePage中设置母版页。 回想一下,我们在母版页教程的“指定标题”、“元标记”和其他 HTML 标头中重新创建了一个自定义基页类(BasePage)。 当前 BasePage 重写 PageOnLoadComplete 的方法,在该方法中,它将基于网站地图数据设置页面 Title 的属性。 让我们进行更新 BasePage 以替代 OnPreInit 方法以编程方式指定母版页。

Protected Overrides Sub OnPreInit(ByVal e As System.EventArgs)
 Me.MasterPageFile = "~/Site.master" 
 MyBase.OnPreInit(e)
End Sub

由于所有内容页都派生自 BasePage,因此所有这些页面现在都以编程方式分配了母版页。 此时, PreInit 事件处理程序 Default.aspx.vb 是多余的;可以随意将其删除。

指令@Page是什么?

可能有点令人困惑的是,内容页 MasterPageFile 的属性现在在两个位置指定:以编程方式在 BasePageOnPreInit 的方法中,以及通过 MasterPageFile 每个内容页 @Page 指令中的属性。

页面生命周期中的第一个阶段是初始化阶段。 在此阶段,Page为对象的MasterPageFile属性分配指令中的@Page属性值MasterPageFile(如果提供)。 PreInit 阶段遵循初始化阶段,在这里,我们以编程方式设置 Page 对象的 MasterPageFile 属性,从而覆盖从 @Page 指令分配的值。 由于我们正在以编程方式设置Page对象的MasterPageFile属性,因此我们可以从@Page指令中删除MasterPageFile该属性,而不会影响最终用户的体验。 若要说服自己,请继续从指令Default.aspx中删除MasterPageFile该属性@Page,然后通过浏览器访问页面。 正如预期的那样,输出与删除属性之前相同。

属性是通过 MasterPageFile 指令设置 @Page 的,还是以编程方式设置的,与最终用户的体验无关。 但是, MasterPageFile 在设计时,Visual Studio 使用指令中的 @Page 属性在设计器中生成 WYSIWYG 视图。 如果在 Visual Studio 中返回 Default.aspx 并导航到设计器,则会看到消息“母版页错误:页面具有需要母版页引用但未指定任何控件”(请参阅图 2)。

简言之,需要在指令中@Page保留该MasterPageFile属性才能在 Visual Studio 中享受丰富的设计时体验。

Visual Studio 使用 <span 类=@Page指令的 MasterPageFile 属性来呈现设计视图“/>

图 02:Visual Studio 使用 @Page 指令的属性 MasterPageFile 呈现设计视图(单击以查看全尺寸图像

步骤 3:创建备用母版页

由于内容页的母版页可以在运行时以编程方式设置,因此可以根据某些外部条件动态加载特定母版页。 在网站布局需要因用户而异的情况下,此功能非常有用。 例如,博客引擎 Web 应用程序可能允许用户为其博客选择布局,其中每个布局都与不同的母版页相关联。 在运行时,当访问者查看用户的博客时,Web 应用程序需要确定博客的布局,并将相应的母版页与内容页动态关联。

让我们看看如何在运行时根据一些外部条件动态加载母版页。 我们的网站目前只包含一个母版页(Site.master)。 我们需要另一个母版页来说明在运行时选择母版页。 此步骤重点介绍如何创建和配置新的母版页。 步骤 4 查看确定在运行时要使用的母版页。

在名为 <a0/> 的根文件夹中创建新的母版页。 此外,将新的样式表添加到名为 AlternateStyles.css“.

将另一个母版页和 CSS 文件添加到网站

图 03:向网站添加另一个母版页和 CSS 文件(单击可查看全尺寸图像

我设计了 Alternate.master 母版页,使标题显示在页面顶部、居中和海军背景上。 我分配了左列,并在 ContentPlaceHolder 控件下 MainContent 移动了该内容,该控件现在跨越页面的整个宽度。 此外,我取消了无序课程列表,并将其替换为上面的 MainContent水平列表。 我还更新了母版页使用的字体和颜色(以及扩展后的内容页)。 图 4 显示 Default.aspx 使用 Alternate.master 母版页时。

注意

ASP.NET 包括定义 主题的功能。 主题是图像、CSS 文件和样式相关的 Web 控件属性设置的集合,可在运行时应用于页面。 如果网站的布局仅在显示的图像及其 CSS 规则中不同,则主题是一种使用主题的方式。 如果布局具有更大的差异,例如使用不同的 Web 控件或具有完全不同的布局,则需要使用单独的母版页。 有关主题的详细信息,请参阅本教程末尾的“进一步阅读”部分。

我们的内容页面现在可以使用新的外观

图 04:我们的内容页面现在可以使用新的外观(单击以查看全尺寸图像

当母版页和内容页的标记融合时, MasterPage 类会检查以确保内容页中的每个内容控件引用母版页中的 ContentPlaceHolder。 如果找到引用不存在的 ContentPlaceHolder 的内容控件,则会引发异常。 换句话说,必须向内容页分配母版页,该母版页具有内容页中每个内容控件的 ContentPlaceHolder。

Site.master 版页包括四个 ContentPlaceHolder 控件:

  • head
  • MainContent
  • QuickLoginUI
  • LeftColumnContent

我们网站中的一些内容页面仅包含一两个内容控件;其他项包括每个可用 ContentPlaceHolders 的内容控件。 如果我们的新母版页 (Alternate.master) 可能曾经分配给所有 ContentPlaceHolders Site.master 具有 Content Controls 的内容页,那么它必须 Alternate.master 同时包含与 ContentPlaceHolder 控件相同的内容页 Site.master

若要使 Alternate.master 母版页看起来类似于我的(请参阅图 4),请先在样式表中定义母版页的样式 AlternateStyles.css 。 将以下规则添加到 AlternateStyles.css

body 
{
 font-family: Comic Sans MS, Arial; 
 font-size: medium; 
 margin: 0px; 
} 
#topContent 
{ 
 text-align: center; 
 background-color: Navy; 
 color: White; 
 font-size: x-large;
 text-decoration: none; 
 font-weight: bold; 
 padding: 10px; 
 height: 50px;
} 
#topContent a 
{ 
 text-decoration: none; 
 color: White; 
} 
#navContent 
{ 
 font-size: small; 
 text-align: center; 
} 
#footerContent 
{ 
 padding: 10px; 
 font-size: 90%; 
 text-align: center; 
 border-top: solid 1px black; 
} 
#mainContent 
{ 
 text-align: left; 
 padding: 10px;
}

接下来,将以下声明性标记添加到 Alternate.master。 如所见,Alternate.master包含四个 ContentPlaceHolder 控件,其值与 ContentPlaceHolder Site.master控件的值相同ID。 此外,它还包括 ScriptManager 控件,对于使用 ASP.NET AJAX 框架的网站中的页面来说是必需的。

<!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 id="Head1" runat="server"> 
 <title>Untitled Page</title>
 <asp:ContentPlaceHolder id="head" runat="server">
 </asp:ContentPlaceHolder> 
 <link href="AlternateStyles.css" rel="stylesheet" type="text/css"/> 
</head> 
<body> 
 <form id="form1" runat="server"> 
 <asp:ScriptManager ID="MyManager" runat="server"> 
 </asp:ScriptManager>
 <div id="topContent">
 <asp:HyperLink ID="lnkHome" runat="server" NavigateUrl="~/Default.aspx" 
 Text="Master Pages Tutorials" /> 
 </div>
 <div id="navContent"> 
 <asp:ListView ID="LessonsList" runat="server" 
 DataSourceID="LessonsDataSource">
 <LayoutTemplate>
 <asp:PlaceHolder runat="server" ID="itemPlaceholder" /> 
 </LayoutTemplate>
 <ItemTemplate>
 <asp:HyperLink runat="server" ID="lnkLesson" 
 NavigateUrl='<%# Eval("Url") %>' 
 Text='<%# Eval("Title") %>' /> 
 </ItemTemplate>
 <ItemSeparatorTemplate> | </ItemSeparatorTemplate> 
 </asp:ListView>
 <asp:SiteMapDataSource ID="LessonsDataSource" runat="server" 
 ShowStartingNode="false" /> 
 </div> 
 <div id="mainContent">
 <asp:ContentPlaceHolder id="MainContent" runat="server"> 
 </asp:ContentPlaceHolder>
 </div>
 <div id="footerContent">
 <p> 
 <asp:Label ID="DateDisplay" runat="server"></asp:Label> 
 </p>
 <asp:ContentPlaceHolder ID="QuickLoginUI" runat="server"> 
 </asp:ContentPlaceHolder>
 <asp:ContentPlaceHolder ID="LeftColumnContent" runat="server"> 
 </asp:ContentPlaceHolder>
 </div> 
 </form>
</body> 
</html>

测试新母版页

若要测试此新的母版页, BasePage 请更新类 OnPreInit 的方法,以便 MasterPageFile 为属性分配值 "~/Alternate.maser" ,然后访问网站。 每一页都应正常运行,但两个页面除外: ~/Admin/AddProduct.aspx~/Admin/Products.aspx。 将产品添加到 DetailsView 将导致~/Admin/AddProduct.aspxNullReferenceException尝试设置母版页属性的代码GridMessageText行。 访问~/Admin/Products.aspxInvalidCastException页面加载时,将引发消息:“无法将类型为”ASP.alternate_master“的对象强制转换为类型”ASP.site_master”。

发生这些错误的原因是 Site.master 代码隐藏类包括未在 中 Alternate.master定义的公共事件、属性和方法。 这两页 @MasterType 的标记部分具有引用母版页的 Site.master 指令。

<%@ MasterType VirtualPath="~/Site.master" %>

此外,DetailsView 的 ItemInserted 事件处理程序包括 ~/Admin/AddProduct.aspx 将松散类型 Page.Master 属性强制转换为类型的 Site对象的代码。 指令 @MasterType (以这种方式使用)和事件处理程序中的 ItemInserted 强制转换紧密耦合 ~/Admin/AddProduct.aspx 母版页和 ~/Admin/Products.aspx 页面 Site.master

为了打破这种紧密耦合,我们可以拥有 Site.masterAlternate.master 派生自包含公共成员定义的公用基类。 接下来,我们可以更新 @MasterType 指令以引用此通用基类型。

创建自定义基母版页类

将一个新类文件添加到 App_Code 命名 BaseMasterPage.vb 的文件夹,并将其派生自 System.Web.UI.MasterPage。 我们需要定义 RefreshRecentProductsGrid 方法和 GridMessageText 属性 BaseMasterPage,但我们不能简单地从那里 Site.master 移动它们,因为这些成员使用特定于 Site.master 母版页的 Web 控件( RecentProducts GridView 和 GridMessage Label)。

我们需要执行的操作是以这样的方式配置 BaseMasterPage 这些成员,以便定义这些成员,但实际上由 BaseMasterPage派生类(Site.masterAlternate.master)实现。 通过将类标记为其成员MustOverrideMustInherit可以采用这种类型的继承。 简言之,将这些关键字添加到类及其两个成员将宣布 BaseMasterPage 尚未实现 RefreshRecentProductsGridGridMessageText但其派生类将报出。

我们还需要定义事件 PricesDoubledBaseMasterPage 并提供派生类引发事件的方法。 .NET Framework 中用于促进此行为的模式是在基类中创建公共事件,并添加一个名为 OnEventName受保护的可重写方法。 然后,派生类可以调用此方法来引发事件,也可以重写它以在引发事件之前或之后立即执行代码。

更新类 BaseMasterPage ,使其包含以下代码:

Public MustInherit Class BaseMasterPage 
 Inherits System.Web.UI.MasterPage 
 Public Event PricesDoubled As EventHandler
 Protected Overridable Sub OnPricesDoubled(ByVal e As EventArgs)
 RaiseEvent PricesDoubled(Me, e)
 End Sub
 Public MustOverride Sub RefreshRecentProductsGrid() 
 Public MustOverride Property GridMessageText() As String 
End Class

接下来,转到 Site.master 代码隐藏类并使其派生自 BaseMasterPage。 因为 BaseMasterPage 包含标记 MustOverride 的成员,因此需要重写此处 Site.master的这些成员。 将 Overrides 关键字添加到方法和属性定义。 此外,使用对基类OnPricesDoubled方法的调用更新 Button Click 事件处理程序中DoublePrice引发PricesDoubled事件的代码。

这些修改后, Site.master 代码隐藏类应包含以下代码:

Partial Class Site 
 Inherits BaseMasterPage
 Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
 DateDisplay.Text = DateTime.Now.ToString("dddd, MMMM dd")
 End Sub
 Public Overrides Sub RefreshRecentProductsGrid() 
 RecentProducts.DataBind()
 End Sub 
 Public Overrides Property GridMessageText() As String 
 Get
 Return GridMessage.Text
 End Get 
 Set(ByVal Value As String) 
 GridMessage.Text = Value 
 End Set
 End Property 
 Protected Sub DoublePrice_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles DoublePrice.Click 
 ' Double the prices 
 DoublePricesDataSource.Update()
 ' Refresh RecentProducts 
 RecentProducts.DataBind()
 ' Raise the PricesDoubled event
 MyBase.OnPricesDoubled(EventArgs.Empty)
 End Sub 
End Class

我们还需要更新 Alternate.master代码隐藏类来派 BaseMasterPage 生和重写这两 MustOverride 个成员。 但是,由于 Alternate.master 不包含列出最新产品的 GridView,也不包含在将新产品添加到数据库后显示消息的标签,因此这些方法无需执行任何操作。

Partial Class Alternate 
 Inherits BaseMasterPage
 Public Overrides Property GridMessageText() As String 
 Get
 Return String.Empty
 End Get
 Set(ByVal value As String) 
 ' Do nothing 
 End Set 
 End Property 
 Public Overrides Sub RefreshRecentProductsGrid()
 ' Do nothing 
 End Sub 
End Class

引用基母版页类

完成该 BaseMasterPage 类并扩展了两个母版页后,最后一步是更新 ~/Admin/AddProduct.aspx~/Admin/Products.aspx 页面以引用此常见类型。 首先从以下两个页面中更改 @MasterType 指令:

<%@ MasterType VirtualPath="~/Site.master" %>

更改为:

<%@ MasterType TypeName="BaseMasterPage" %>

属性 @MasterType 现在引用基类型(BaseMasterPage)而不是引用文件路径。 因此,这两个页面的代码隐藏类中使用的强类型 Master 属性现在的类型 BaseMasterPage (而不是类型 Site)。 随着此更改的重新访问 ~/Admin/Products.aspx。 以前,这会导致强制转换错误,因为页面配置为使用 Alternate.master 母版页,但 @MasterType 指令引用了 Site.master 该文件。 但现在页面呈现时没有错误。 这是因为 Alternate.master 母版页可以强制转换为类型的 BaseMasterPage 对象(因为它扩展了它)。

需要进行 ~/Admin/AddProduct.aspx一个小的改变。 DetailsView 控件的 ItemInserted 事件处理程序同时使用强类型 Master 属性和松散类型 Page.Master 属性。 我们在更新 @MasterType 指令时修复了强类型引用,但仍需要更新松散类型的引用。 替换以下代码行:

Dim myMasterPage As Site = CType(Page.Master, Site)

使用以下命令,该类型转换为 Page.Master 基类型:

Dim myMasterPage As BaseMasterPage = CType(Page.Master, BaseMasterPage)

步骤 4:确定要绑定到内容页的母版页

我们的 BasePage 类当前将所有内容页 MasterPageFile 的属性设置为页面生命周期的 PreInit 阶段中的硬编码值。 我们可以更新此代码以基于某些外部因素的母版页。 也许要加载的母版页取决于当前登录用户的首选项。 在这种情况下,我们需要在方法BasePageOnPreInit编写代码,以便查找当前访问用户的母版页首选项。

让我们创建一个网页,允许用户选择要使用的母版页, Site.master 或者 Alternate.master - 并在会话变量中保存此选项。 首先,在名为 <a0/a0> 的根目录中创建新的网页。 创建此页面(或任何其他内容页)时,无需将其绑定到母版页,因为母版页是以编程方式设置的 BasePage。 但是,如果不将新页面绑定到母版页,则新页面的默认声明性标记包含 Web 窗体和母版页提供的其他内容。 需要手动将此标记替换为相应的内容控件。 因此,我发现将新的 ASP.NET 页绑定到母版页更容易。

注意

因为 Site.masterAlternate.master 具有相同的 ContentPlaceHolder 控件集,因此创建新内容页时选择的母版页并不重要。 为了保持一致性,我建议使用 Site.master

向网站添加新内容页

图 05:向网站添加新内容页(单击可查看全尺寸图像

更新 Web.sitemap 文件以包含本课程的条目。 在母版页和 ASP.NET AJAX 课程的下面 <siteMapNode> 添加以下标记:

<siteMapNode url="~/ChooseMasterPage.aspx" title="Choose a Master Page" />

在将任何内容添加到 ChooseMasterPage.aspx 页面之前,需要花点时间更新页面的代码隐藏类,使其派生自 BasePage (而不是 System.Web.UI.Page)。 接下来,将 DropDownList 控件添加到页面,将其 ID 属性设置为 MasterPageChoice该页,并添加两个 ListItems, Text 其值为“~/Site.master”和“~/Alternate.master”。

向页面添加按钮 Web 控件,并将按钮 Web 控件及其 ID 属性 Text 分别设置为 SaveLayout “保存布局选择”。 此时,页面的声明性标记应如下所示:

<p> 
 Your layout choice: 
 <asp:DropDownList ID="MasterPageChoice" runat="server"> 
 <asp:ListItem>~/Site.master</asp:ListItem>
 <asp:ListItem>~/Alternate.master</asp:ListItem>
 </asp:DropDownList> 
</p> 
<p> 
 <asp:Button ID="SaveLayout" runat="server" Text="Save Layout Choice" /> 
</p>

首次访问页面时,我们需要显示用户当前选定的母版页选项。 创建 Page_Load 事件处理程序并添加以下代码:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
 If Not Page.IsPostBack Then 
 If Session("MyMasterPage") IsNot Nothing Then 
 Dim li As ListItem = MasterPageChoice.Items.FindByText(Session("MyMasterPage").ToString())
 If li IsNot Nothing Then 
 li.Selected = True
 End If 
 End If 
 End If 
End Sub

上述代码仅在第一页访问(而不是后续回发时)执行。 它首先检查会话变量 MyMasterPage 是否存在。 如果这样做,它会尝试在 DropDownList 中找到匹配的 MasterPageChoice ListItem。 如果找到匹配的 ListItem,则其 Selected 属性设置为 True

我们还需要将用户选择的代码保存到 MyMasterPage Session 变量中。 为 SaveLayout Button Click 的事件创建事件处理程序并添加以下代码:

Protected Sub SaveLayout_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SaveLayout.Click 
 Session("MyMasterPage") = MasterPageChoice.SelectedValue 
 Response.Redirect("ChooseMasterPage.aspx")
End Sub

注意

Click 回发时事件处理程序执行时,已选择母版页。 因此,在下一页访问之前,用户的下拉列表选择不会生效。 强制 Response.Redirect 浏览器重新请求 ChooseMasterPage.aspx

完成页面后ChooseMasterPage.aspx,最终任务是BasePage基于会话变量的值MyMasterPage分配MasterPageFile属性。 如果未设置会话变量,则默认为 BasePage Site.master

Protected Overrides Sub OnPreInit(ByVal e As System.EventArgs)
 SetMasterPageFile() 
 MyBase.OnPreInit(e)
End Sub 
Protected Overridable Sub SetMasterPageFile() 
 Me.MasterPageFile = GetMasterPageFileFromSession() 
End Sub 
Protected Function GetMasterPageFileFromSession() As String 
 If Session("MyMasterPage") Is Nothing Then
 Return "~/Site.master"
 Else 
 Return Session("MyMasterPage").ToString() 
 End If 
End Function

注意

我将对象属性从事件处理程序中移PageMasterPageFileOnPreInit的代码,并移到了两个单独的方法中。 第一个方法 SetMasterPageFile将属性分配给 MasterPageFile 第二个方法 GetMasterPageFileFromSession返回的值。 我标记了 SetMasterPageFile 该方法 Overridable ,以便扩展 BasePage 的未来类可以根据需要选择性地重写它来实现自定义逻辑。 在下一教程中,我们将看到重写 BasePage's SetMasterPageFile 属性的示例。

使用此代码就位后,请访问 ChooseMasterPage.aspx 页面。 最初, Site.master 母版页处于选中状态(见图 6),但用户可以从下拉列表中选择不同的母版页。

使用 Site.master 母版页显示内容页

图 06:使用 Site.master 母版页显示内容页(单击以查看全尺寸图像

内容页现在使用 Alternate.master 母版页显示

图 07:现在使用母版页显示 Alternate.master 内容页(单击以查看全尺寸图像

总结

访问内容页面时,其内容控件与其母版页的 ContentPlaceHolder 控件融合在一起。 内容页的母版页由 PageMasterPageFile 的属性表示,该属性在初始化阶段分配给 @Page 指令 MasterPageFile 的属性。 如本教程所示,只要在 PreInit 阶段结束之前,就可以向属性分配值 MasterPageFile 。 能够以编程方式指定母版页为更高级的方案打开大门,例如基于外部因素动态将内容页绑定到母版页。

快乐编程!

深入阅读

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

关于作者

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

特别感谢

本教程系列由许多有用的审阅者审阅。 本教程的主要审阅者是 Suchi Banerjee。 有兴趣查看即将发布的 MSDN 文章? 如果是这样,请在以下位置放置我一行 mitchell@4GuysFromRolla.com