共用方式為


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

作者:Scott Mitchell

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

簡介

由於使用主版頁面建立全網站版面配置中的首例,所有內容頁面都透過 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屬性

這個融合的主版頁面部分取決於物件MasterPageFile屬性的值PageMasterPageFile在指示詞中@Page設定 屬性具有在初始化階段指派 屬性的凈效果PageMasterPageFile,這是頁面生命週期的第一個階段。 或者,我們可以以程式設計方式設定此屬性。 不過,在圖 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設定主版頁面。 回想一下,我們已在主版頁面教學課程中指定標題、中繼標記和其他 HTML 標頭中,建立自定義基頁類別 (BasePage)。 目前 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 屬性會指派 MasterPageFile 指示詞中的 @Page 屬性值(如果提供的話)。 PreInit 階段會遵循初始化階段,而在這裡,我們以程式設計方式設定 Page 對象的 MasterPageFile 屬性,進而覆寫從 @Page 指示詞指派的值。 因為我們以程式設計方式設定Page物件的 MasterPageFile 屬性,因此我們可以從 @Page 指示詞中移除 MasterPageFile 屬性,而不會影響終端用戶的體驗。 若要說服自己,請繼續從中的 @Page Default.aspx 指示詞中移除 MasterPageFile 屬性,然後瀏覽頁面,並瀏覽瀏覽器。 如您所預期,輸出與移除屬性之前相同。

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

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

Visual Studio 使用 <span 類別=@Page指示詞的 MasterPageFile 屬性來呈現設計視圖“ />

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

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

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

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

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

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

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

我設計了 Alternate.master 主版頁面,讓標題顯示在頁面頂端,置中和海軍背景。 我已分配左欄,並將該內容移至 ContentPlaceHolder 控件下方 MainContent ,而該控件現在會跨越頁面的整個寬度。 此外,我已取消排序的 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 具有 Content 控件的內容頁面,則也必須 Alternate.master 包含與 Site.master相同的 ContentPlaceHolder 控件。

若要讓您的 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.aspx ,會產生 NullReferenceException 嘗試設定主版頁面 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/AddProduct.aspx~/Admin/Products.aspx 頁面至 Site.master 主版頁面。

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

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

將新的類別檔案新增至 App_Code 名為 BaseMasterPage.cs 的資料夾,並將其衍生自 System.Web.UI.MasterPage。 我們需要在 中定義 RefreshRecentProductsGrid 方法和 GridMessageText 屬性,但我們不能簡單地從Site.master那裡移動它們,因為這些成員會使用主版頁面特定的 Site.master Web 控件(RecentProductsGridView 和 GridMessage Label)。BaseMasterPage

我們需要做的是 BaseMasterPage ,以這樣的方式設定這些成員定義在那裡,但實際上是由 BaseMasterPage的衍生類別 (Site.masterAlternate.master) 實作。 這種繼承類型可以藉由將 類別及其成員標示為 abstract。 簡言之,將 關鍵詞新增 abstract 至這兩個成員會宣告 BaseMasterPage 尚未實 RefreshRecentProductsGrid 作 和 GridMessageText,但其衍生類別將會。

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

更新類別 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,也不包含在將新產品新增至資料庫之後顯示訊息的 Label,因此這些方法不需要執行任何動作。

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 別屬性現在為類型 BaseMasterPage (而不是 類型 Site)。 有了這項變更,請重新流覽 ~/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 階段中的硬式編碼值。 我們可以更新此程序代碼,以根據某些外部因素來建立主版頁面的基礎。 也許要載入的主版頁面取決於目前登入使用者的喜好設定。 在此情況下,我們需要在方法BasePageOnPreInit撰寫程式代碼,以查閱目前瀏覽的使用者主版頁面喜好設定。

讓我們建立一個網頁,讓用戶選擇要使用的主版頁面 - 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,並新增兩個 ListItems,其 Text 值為 “~/Site.master” 和 “~/Alternate.master”。

將 Button 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 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 代碼。 建立 SaveLayout Button Click 事件的事件處理程式,並新增下列程式代碼:

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 屬性。 如果未將會話變數設定為 ,則預設為 BasePage Site.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(); 
}

注意

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

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

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

圖 06:使用 Site.master 主版頁面顯示內容頁面 (按兩下以檢視完整大小的影像

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

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

摘要

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

快樂程式!

深入閱讀

有關本教學課程中討論的主題的更多資訊,請參閱以下資源:

關於作者

斯科特·米切爾,多個 ASP/ASP.NET 書籍的作者,4GuysFromRolla.com 的創始人,自1998年以來一直與Microsoft Web 技術合作。 Scott 擔任獨立顧問、講師和作家。 他的最新書是 山姆斯在24小時內 ASP.NET 3.5。 斯科特可以透過 mitchell@4GuysFromRolla.com 他在的部落格聯繫到或通過他的博客 http://ScottOnWriting.NET

特別感謝

本教學課程系列已經過許多熱心的檢閱者檢閱。 本教學課程的主要檢閱者是 Suchi Banerjee。 有興趣檢閱我即將推出的 MSDN 文章嗎? 如果是,請將一行放在 mitchell@4GuysFromRolla.com