以程式設計方式指定主版頁面 (C#)

作者 :Scott Mitchell

查看透過 PreInit 事件處理程式以程式設計方式設定內容頁面的主版頁面。

簡介

由於使用主 版頁面建立 Site-Wide 版面配置中的內嵌範例,因此所有內容頁面都會透過 MasterPageFile 指示詞中的 @Page 屬性以宣告方式參考其主版頁面。 例如,下列 @Page 指示詞會將內容頁面連結至主版頁面 Site.master

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

Page命名空間中的 System.Web.UI 類別包含MasterPageFile屬性,這個屬性會傳回內容頁面主版頁面的路徑;它是 指示詞所設定的@Page這個屬性。 這個屬性也可以用來以程式設計方式指定內容頁面的主版頁面。 如果您想要根據外部因素動態指派主版頁面,例如瀏覽頁面的使用者,此方法非常有用。

在本教學課程中,我們會將第二個主版頁面新增至網站,並動態決定要在運行時間使用的主版頁面。

步驟 1:查看頁面生命週期

每當要求抵達網頁網頁的 ASP.NET 頁面時,ASP.NET 引擎必須將頁面的內容控件結合至主版頁面的對應 ContentPlaceHolder 控件。 此融合會建立單一控件階層,然後可繼續進行一般頁面生命週期。

圖 1 說明此融合。 圖 1 中的步驟 1 顯示初始內容和主版頁面控件階層。 在 PreInit 階段的結尾,頁面的內容控件會新增至主版頁面中對應的 ContentPlaceHolders, (步驟 2) 。 在此融合之後,主版頁面會作為融合控件階層的根目錄。 接著,這個結合的控件階層會新增至頁面,以產生完成的控制階層 (步驟 3) 。 最終結果是頁面的控制階層包含融合的控件階層。

主版頁面和內容頁面的控件階層會在 PreInit 階段期間整合在一起

圖 01:主版頁面和內容頁面的控件階層會在 PreInit 階段期間整合在一起, (按兩下即可檢視完整大小的影像)

步驟 2:從程式代碼設定MasterPageFile屬性

這個融合中的主版頁面元件取決於 Page 對象的 MasterPageFile 屬性值。 MasterPageFile在指示詞中@Page設定 屬性具有在初始化階段中指派 Page屬性MasterPageFile的凈效果,這是頁面生命週期的第一個階段。 或者,我們可以以程式設計方式設定這個屬性。 不過,在圖 1 中的融合發生之前,必須設定這個屬性。

在 PreInit 階段開始時, Page 對象會引發其 PreInit 事件 ,並呼叫其 OnPreInit 方法。 若要以程式設計方式設定主版頁面,我們可以建立事件的事件處理程式 PreInit 或覆寫 OnPreInit 方法。 讓我們看看這兩種方法。

首先,開啟 Default.aspx.cs網站首頁的程序代碼後置類別檔案。 輸入下列程式代碼,以新增頁面 PreInit 事件的事件處理程式:

protected void Page_PreInit(object sender, EventArgs e) 
{ 
}

從這裡我們可以設定 MasterPageFile 屬性。 更新程序代碼,以便將值 “~/Site.master” 指派給 MasterPageFile 屬性。

protected void Page_PreInit(object sender, EventArgs e) 
{
    this.MasterPageFile = "~/Site.master"; 
}

如果您設定斷點並開始偵錯,您會看到每當 Default.aspx 瀏覽頁面或每當有回傳至此頁面時, Page_PreInit 事件處理程式就會執行 ,並將 MasterPageFile 屬性指派給 “~/Site.master”。

或者,您可以覆寫 Page 類別的方法, OnPreInit 並在該處設定 MasterPageFile 屬性。 在此範例中,我們不會在特定頁面中設定主版頁面,而是從 BasePage設定主版頁面。 回想一下,我們在主版頁面教學課程中 () 建立自定義基頁類別 BasePage) 指定 標題、中繼標籤和其他 HTML 標頭 。 目前 BasePagePage 覆寫 類別的 OnLoadComplete 方法,其中會根據網站地圖數據來設定頁面 Title 的屬性。 讓我們更新 BasePage 以覆寫 OnPreInit 方法來以程序設計方式指定主版頁面。

protected override void OnPreInit(EventArgs e) 
{ 
    this.MasterPageFile = "~/Site.master"; 
    base.OnPreInit(e); 
}

由於我們的所有內容頁面都衍生自 BasePage,因此所有頁面現在都會以程序設計方式指派主版頁面。 此時 中的PreInitDefault.aspx.cs事件處理程式是多餘的,您可以隨意移除它。

指示詞呢@Page

可能有點令人困惑的是,內容頁面 MasterPageFile 的屬性現在已在兩個位置指定:以程序設計方式在 BasePage 類別的 OnPreInit 方法中,以及 MasterPageFile 透過每個內容頁面 @Page 指示詞中的屬性。

頁面生命週期中的第一個階段是初始化階段。 在這個階段期間,Page如果 MasterPageFile) 提供屬性,則會將 指示詞中的 @Page 屬性值指派 MasterPageFile (。 PreInit 階段會遵循初始化階段,在這裡我們以程式設計方式設定 Page 對象的 MasterPageFile 屬性,進而覆寫從 @Page 指示詞指派的值。 因為我們是以程式設計方式設定 Page 物件的 MasterPageFile 屬性,所以可以從指示詞中移除 MasterPageFile 屬性 @Page ,而不會影響用戶體驗。 若要確信自己,請繼續並從 @Page 中的 Default.aspx 指示詞中移除 MasterPageFile 屬性,然後瀏覽網頁瀏覽瀏覽器。 如您所預期,輸出與移除屬性之前相同。

屬性是 MasterPageFile 透過 @Page 指示詞設定,還是以程式設計方式設定為用戶經驗不連續。 不過,MasterPageFile在設計時間期間,Visual Studio 會使用 指示詞中的 @Page 屬性,在 Designer 中產生 WYSIWYG 檢視。 如果您在 Visual Studio 中返回 Default.aspx 並流覽至 Designer 您會看到訊息:「主版頁面錯誤:頁面具有需要主版頁面參考的控件,但未指定任何控件」, (請參閱圖 2) 。

簡單地說,您必須將 MasterPageFile 屬性保留在 指示詞中 @Page ,才能在Visual Studio中享有豐富的設計時間體驗。

Visual Studio 使用 <span class=@Page 指示詞的 MasterPageFile 屬性來轉譯設計視圖“ />

圖 02:Visual Studio 使用 @Page 指示詞的屬性 MasterPageFile 來轉譯設計視圖 (按兩下即可檢視完整大小的影像)

步驟 3:建立替代主版頁面

因為內容頁面的主版頁面可以在運行時間以程序設計方式設定,所以可以根據某些外部準則動態載入特定主版頁面。 在網站版面配置需要根據使用者而有所不同的情況下,這項功能非常有用。 例如,部落格引擎 Web 應用程式可讓用戶選擇其部落格的配置,其中每個配置都與不同的主版頁面相關聯。 在運行時間,當訪客檢視使用者的部落格時,Web 應用程式必須判斷部落格的配置,並動態將對應的主版頁面與內容頁面產生關聯。

讓我們檢查如何根據某些外部準則,在運行時間動態載入主版頁面。 我們的網站目前只包含一個主版頁面 (Site.master) 。 我們需要另一個主版頁面,以說明在運行時間選擇主版頁面。 此步驟著重於建立和設定新的主版頁面。 步驟 4 會查看判斷要在運行時間使用的主版頁面。

在名為 Alternate.master的根資料夾中建立新的主版頁面。 此外,將新的樣式表單新增至名為 AlternateStyles.css的網站。

將另一個主版頁面和 CSS 檔案新增至網站

圖 03:將另一個主版頁面和 CSS 檔案新增至網站 (按兩下即可檢視完整大小的影像)

我設計 Alternate.master 了主版頁面,讓標題顯示在頁面頂端、置中和位於一個淺色背景上。 我已分配左欄,並將該內容移至 ContentPlaceHolder 控件下方 MainContent ,現在會跨越頁面的整個寬度。 此外,I nixed 未排序的 Lessons 清單,並將它取代為上方 MainContent的水準清單。 我也會更新主版頁面所使用的字型和色彩 (,並依延伸模組更新其內容頁面) 。 圖 4 顯示 Default.aspx 使用 Alternate.master 主版頁面時。

注意

ASP.NET 包括定義 主題的能力。 主題是影像、CSS 檔案和樣式相關 Web 控件屬性設定的集合,可在運行時間套用至頁面。 如果您的網站版面配置只與顯示的影像不同,以及其 CSS 規則,主題就是要前往的方式。 如果版面配置明顯不同,例如使用不同的 Web 控制件或擁有完全不同的版面配置,則您必須使用不同的主版頁面。 如需主題的詳細資訊,請參閱本教學課程結尾的一節。

我們的內容頁面現在可以使用新的外觀和風格

圖 04:我們的內容頁面現在可以使用新的外觀和風格, (按兩下即可檢視完整大小的影像)

當主版和內容頁面的標記結合時,類別會 MasterPage 檢查以確定內容頁面中的每個 Content 控件都會參考主版頁面中的 ContentPlaceHolder。 如果找到參考不存在 ContentPlaceHolder 的內容控件,則會擲回例外狀況。 換句話說,指派給內容頁面的主版頁面對於內容頁面中的每個內容控件都必須有 ContentPlaceHolder。

Site.master 版頁面包含四個 ContentPlaceHolder 控件:

  • head
  • MainContent
  • QuickLoginUI
  • LeftColumnContent

我們網站的部分內容頁面只包含一或兩個內容控件;其他包含每個可用 ContentPlaceHolders 的內容控件。 如果新的主版頁面 (Alternate.master) 可能已指派給所有 ContentPlaceHolders Site.master 的內容頁面,則其中也必須 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 控件,其值與 中的 Site.masterContentPlaceHolder 控件相同ID。 此外,它也包含 ScriptManager 控制件,這是使用 AJAX 架構 ASP.NET 網站中頁面的必要專案。

<!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.master” 值,然後瀏覽網站。 除了兩個: ~/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 事件處理程式包含將鬆散類型Page.Master屬性轉換成 類型Site物件的程式~/Admin/AddProduct.aspx代碼。 指示@MasterType詞 (以這種方式) ,而事件處理程式中的ItemInserted轉換會將 和 ~/Admin/Products.aspx 頁面緊密結合~/Admin/AddProduct.aspxSite.master主版頁面。

為了中斷這個緊密結合,我們可以擁有 Site.masterAlternate.master 衍生自包含公用成員定義的通用基類。 接著,我們可以更新 @MasterType 指示詞以參考這個通用基底類型。

建立自訂基底主版頁面類別

將新的類別檔案新增至 App_Code 名為 BaseMasterPage.cs 的資料夾,並讓它衍生自 System.Web.UI.MasterPage。 我們需要在 中定義 RefreshRecentProductsGrid 方法和 GridMessageText 屬性,但無法直接從Site.master該處移動它們,因為這些成員會使用主版頁面特定的 Site.master Web 控件, (RecentProducts GridView 和 GridMessageBaseMasterPageLabel) 。

我們需要執行的動作是 BaseMasterPage 透過這類方式來設定這些成員,但實際上是由 BaseMasterPage衍生類別 (Site.masterAlternate.master) 實作。 將 類別及其成員標示為 abstract,即可進行這種類型的繼承。 簡單地說,將 關鍵詞新增 abstract 至這兩個成員會宣告 BaseMasterPage 尚未實 RefreshRecentProductsGrid 作 和 GridMessageText,但其衍生類別將會。

我們也需要在 中BaseMasterPage定義 PricesDoubled 事件,並提供衍生類別來引發事件的方法。 .NET Framework 中使用的模式有助於此行為,就是在基類中建立公用事件,virtual並新增名為OnEventName的受保護方法。 然後衍生類別可以呼叫這個方法來引發事件,也可以覆寫它,在引發事件之前或之後立即執行程序代碼。

更新類別 BaseMasterPage ,使其包含下列程序代碼:

using System; public abstract class BaseMasterPage : System.Web.UI.MasterPage
{ 
    public event EventHandler PricesDoubled; 
    protected virtual void OnPricesDoubled(EventArgs e) 
    { 
        if (PricesDoubled != null) 
        PricesDoubled(this, e); 
    } 
    public abstract void RefreshRecentProductsGrid();
    public abstract string GridMessageText 
    { 
        get; 
        set; 
    } 
}

接下來,移至程式 Site.master 代碼後置類別,並讓它衍生自 BaseMasterPageabstract因為我們BaseMasterPage需要在中Site.master覆寫這些abstract成員。 將 override 關鍵詞新增至 方法和屬性定義。 同時更新程序代碼,以呼叫基類的 OnPricesDoubled 方法,在 Button 的Click事件處理程式中DoublePrice引發 PricesDoubled 事件。

在這些修改之後,程式 Site.master 代碼後置類別應該包含下列程式代碼:

public partial class Site : BaseMasterPage { 
    protected void Page_Load(object sender, EventArgs e) 
    { 
        DateDisplay.Text = DateTime.Now.ToString("dddd, MMMM dd"); 
    } 
    public override void RefreshRecentProductsGrid()
    { 
        RecentProducts.DataBind();
    } 
    public override string GridMessageText
    { 
        get 
        {
            return GridMessage.Text;
        } 
        set
        {
            GridMessage.Text = value; 
        } 
    }
    protected void DoublePrice_Click(object sender, EventArgs e) 
    { 
        // Double the prices 
        DoublePricesDataSource.Update();
        // Refresh RecentProducts 
        RecentProducts.DataBind();
        // Raise the PricesDoubled event
        base.OnPricesDoubled(EventArgs.Empty);
    } 
}

我們也需要更新 Alternate.master的程式代碼後置類別,以衍生自 BaseMasterPage 並覆寫這兩 abstract 個成員。 但是,因為 Alternate.master 不包含列出最新產品或標籤的 GridView,也會在將新產品新增至資料庫之後顯示訊息,因此這些方法不需要執行任何動作。

public partial class Alternate : BaseMasterPage 
{ 
    public override void RefreshRecentProductsGrid() 
    { 
        // Do nothing 
    } 
    public override string GridMessageText 
    { 
        get
        { 
            return string.Empty;
        } 
        set
        {
            // Do nothing 
        } 
    }
}

參考基底主版頁面類別

既然我們已經完成 類別 BaseMasterPage ,並讓兩個主版頁面擴充它,最後一個步驟就是更新 ~/Admin/AddProduct.aspx~/Admin/Products.aspx 頁面來參考這個通用類型。 從下列兩個頁面中變更 @MasterType 指示詞開始:

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

變更為:

<%@ MasterType TypeName="BaseMasterPage" %>

屬性現在會參考基底類型 () ,BaseMasterPage而不是參考檔案路徑@MasterType。 因此,這兩個頁面程序代碼後置類別中使用的強型 Master 別屬性現在是類型 (,而不是類型 BaseMasterPageSite) 。 有了這項變更,請重新流覽 ~/Admin/Products.aspx。 先前,這會導致轉型錯誤,因為頁面已設定為使用 Alternate.master 主版頁面,但 @MasterType 指示詞參考了 Site.master 檔案。 但現在頁面會轉譯而不會發生錯誤。 這是因為 Alternate.master 主版頁面可以轉換成類型 BaseMasterPage 為 (的對象,因為它會將它擴充) 。

在 中 ~/Admin/AddProduct.aspx必須進行一個小變更。 DetailsView 控件的 ItemInserted 事件處理程序同時使用強型 Master 別屬性和鬆散類型 Page.Master 屬性。 我們已修正更新 @MasterType 指示詞時的強型別參考,但仍需要更新鬆散型別的參考。 取代下列程式代碼列:

Site myMasterPage = Page.Master as Site;

使用下列命令,轉換為 Page.Master 基底類型:

BaseMasterPage myMasterPage = Page.Master as BaseMasterPage;

步驟 4:決定要系結至內容頁面的主版頁面

我們的 BasePage 類別目前會將所有內容頁面 MasterPageFile 的屬性設定為頁面生命週期 PreInit 階段中的硬式編碼值。 我們可以更新此程序代碼,以根據某些外部因素來建立主版頁面的基礎。 可能要載入的主版頁面取決於目前登入使用者的喜好設定。 在此情況下,我們需要在 OnPreInit 方法 BasePage 中撰寫程式代碼,以查閱目前瀏覽使用者的主版頁面喜好設定。

讓我們建立一個網頁,讓用戶選擇要使用的主版頁面 , Site.masterAlternate.master - 並將此選項儲存在會話變數中。 首先,在名為 ChooseMasterPage.aspx的根目錄中建立新的網頁。 建立此頁面時 (或任何其他內容頁面,因此) 您不需要將它系結至主版頁面,因為主版頁面是以程序設計方式在 中 BasePage設定。 不過,如果您未將新頁面系結至主版頁面,新頁面的預設宣告式標記會包含網頁窗體和其他主版頁面提供的內容。 您必須以適當的內容控制件手動取代此標記。 基於這個理由,我發現將新的 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,並使用 “~/Site.master” 和 “~/Alternate.master” 的值新增兩個 ListItems Text

將 Button Web 控制項新增至頁面,並將其 IDText 屬性分別設定為 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 void Page_Load(object sender, EventArgs e) 
{ 
    if (!Page.IsPostBack) 
    { 
        if (Session["MyMasterPage"] != null)
        {
            ListItem li = MasterPageChoice.Items.FindByText(Session["MyMasterPage"].ToString());
            if (li != null) 
                li.Selected = true; 
        } 
    }
}

上述程式代碼只會在第一頁流覽 (執行,而不是後續回傳) 。 它會先檢查會話變數 MyMasterPage 是否存在。 如果這樣做,它會嘗試在DropDownList 中尋找相符的 MasterPageChoice ListItem。 如果找到相符的 ListItem,屬性 Selected 會設定為 true

我們也需要將用戶選擇儲存到 Session 變數的程式 MyMasterPage 代碼。 建立 Button Click 事件的事件處理程式SaveLayout,並新增下列程式代碼:

protected void SaveLayout_Click(object sender, EventArgs e)
{
    Session["MyMasterPage"] = MasterPageChoice.SelectedValue;
    Response.Redirect("ChooseMasterPage.aspx"); 
}

注意

Click在事件處理程式在回傳時執行時,已選取主版頁面。 因此,除非下一頁瀏覽,否則使用者的下拉式清單選取將不會生效。 會 Response.Redirect 強制瀏覽器重新要求 ChooseMasterPage.aspx

完成ChooseMasterPage.aspx頁面之後,我們的最後一項工作就是BasePage根據 Session 變數的值MyMasterPage來指派 MasterPageFile 屬性。 如果未將 Session 變數設定為 ,則預設值為 BasePageSite.master

protected override void OnPreInit(EventArgs e) 
{ 
    SetMasterPageFile();
    base.OnPreInit(e); 
} 
protected virtual void SetMasterPageFile()
{ 
    this.MasterPageFile = GetMasterPageFileFromSession();
} 
protected string GetMasterPageFileFromSession() 
{ 
    if (Session["MyMasterPage"] == null) 
        return "~/Site.master";
    else
        return Session["MyMasterPage"].ToString(); 
}

注意

我已將指派 Page 物件 MasterPageFile 屬性的程式 OnPreInit 代碼移出事件處理程式,並移至兩個不同的方法。 這個第一個方法 SetMasterPageFile會將 MasterPageFile 屬性指派給第二個方法 GetMasterPageFileFromSession所傳回的值。 我已建立 SetMasterPageFile 方法 virtual ,讓擴充的未來類別 BasePage 可以視需要選擇性地覆寫它以實作自定義邏輯。 我們將在下一個教學課程中看到覆寫 BasePageSetMasterPageFile 屬性範例。

在此程式代碼就緒后,請瀏覽 ChooseMasterPage.aspx 頁面。 一開始選取 Site.master 主版頁面 (請參閱圖 6) ,但使用者可以從下拉式清單中挑選不同的主版頁面。

使用 Site.master 主版頁面顯示內容頁面

圖 06:使用主版頁面顯示 Site.master 內容頁面 (按鍵即可檢視全大小影像)

內容頁面現在會顯示使用 Alternate.master 主版頁面

圖 07:內容頁面現在會顯示使用 Alternate.master 主版頁面 (按兩下即可檢視完整大小的影像)

摘要

瀏覽內容頁面時,其 Content 控件會與其主版頁面的 ContentPlaceHolder 控件結合。 內容頁面的主版頁面是由 Page 類別的 MasterPageFile 屬性表示,該屬性會在初始化階段指派給 @Page 指示 MasterPageFile 詞的 屬性。 如本教學課程所示,只要我們在 PreInit 階段結束時執行此動作,就可以將值指派給 MasterPageFile 屬性。 能夠以程式設計方式指定主版頁面來開啟更進階案例的門,例如根據外部因素動態將內容頁面系結至主版頁面。

快樂的程序設計!

深入閱讀

如需本教學課程中所討論之主題的詳細資訊,請參閱下列資源:

關於作者

Scott Mitchell 是多個 ASP/ASP.NET 書籍的作者,且 4GuysFromRolla.com 的作者,自 1998 年以來,已與 Microsoft Web 技術合作。 Scott 是獨立顧問、訓練員和作者。 他的最新書籍是 Sams 在 24 小時內自行 ASP.NET 3.5。 您可以在 或 透過在 的http://ScottOnWriting.NET部落格連線mitchell@4GuysFromRolla.com到 Scott。

特別感謝

本教學課程系列是由許多實用的檢閱者檢閱。 本教學課程的首席檢閱者是 Suchi Banerjee。 有興趣檢閱即將推出的 MSDN 文章嗎? 如果是,請將一行放在我 mitchell@4GuysFromRolla.com