多個 ContentPlaceHolders 和預設內容 (C#)

作者 :Scott Mitchell

下載 PDF

檢查如何將多個內容佔位元新增至主版頁面,以及如何在內容佔位元中指定預設內容。

簡介

在上述教學課程中,我們已檢查主版頁面如何讓 ASP.NET 開發人員建立一致的全網站版面配置。 主版頁面會定義其所有內容頁面和可逐頁自定義之區域通用的標記。 在上一個教學課程中,我們建立了簡單的主版頁面 (Site.master) ,以及兩個內容頁面 (Default.aspxAbout.aspx) 。 我們的主版頁面包含兩個名為 headMainContent的 ContentPlaceHolders,分別位於 <head> 元素和 Web Form 中。 雖然內容頁面各有兩個 Content 控制項,但我們只指定對應至 MainContent的標記。

如 中 Site.master兩個 ContentPlaceHolder 控件所辨識,主版頁面可能包含多個 ContentPlaceHolders。 更重要的是,主版頁面可能會指定 ContentPlaceHolder 控件的預設標記。 然後,內容頁面可以選擇性地指定自己的標記,或使用預設標記。 在本教學課程中,我們將探討在主版頁面中使用多個內容控件,並瞭解如何在 ContentPlaceHolder 控件中定義預設標記。

步驟 1:將其他 ContentPlaceHolder 控件新增至主版頁面

許多網站設計都包含畫面上的數個區域,這些區域會逐頁自定義。 Site.master,我們在上一個教學課程中建立的主版頁面包含名為 MainContent的Web Form內的單一 ContentPlaceHolder。 具體而言,此 ContentPlaceHolder 位於 元素內 mainContent<div>

圖 1 顯示 Default.aspx 透過瀏覽器檢視時。 以紅色圓圈的區域是對應至 MainContent的頁面特定標記。

圓圈區域顯示目前可逐頁自定義的區域

圖 01:圓形區域顯示目前可逐頁自定義的區域, (按兩下即可檢視完整大小的影像)

假設除了圖 1 所示的區域之外,我們也需要在 [課程] 和 [新聞] 區段下方的左側數據行中新增頁面特定專案。 為了達成此目的,我們會將另一個 ContentPlaceHolder 控件新增至主版頁面。 若要跟著做,請在 Visual Web Developer 中開啟 Site.master 主版頁面,然後將 ContentPlaceHolder 控件從 [工具箱] 拖曳到設計工具的 [新聞] 區段之後。 將 ContentPlaceHolder 的 ID 設定為 LeftColumnContent

將 ContentPlaceHolder 控制項新增至主版頁面的左欄

圖 02:將 ContentPlaceHolder 控件新增至主版頁面的左欄, (按兩下即可檢視完整大小的影像)

藉由將 ContentPlaceHolder 新增 LeftColumnContent 至主版頁面,我們可以藉由在設定為 的頁面中包含 ContentPlaceHolderIDLeftColumnContentContent 控件,以逐頁定義此區域的內容。 我們會在步驟 2 中檢查此程式。

步驟 2:在內容頁面中定義新 ContentPlaceHolder 的內容

將新的內容頁面新增至網站時,Visual Web Developer 會自動在選取的主版頁面中為每個 ContentPlaceHolder 建立內容控件。 在步驟 1 中將 ContentPlaceHolder 新增至主版頁面之後,新的 ASP.NET 頁面現在會有三個 LeftColumnContent 內容控件。

為了說明這一點,請將新的內容頁面新增至系結至Site.master主版頁面的MultipleContentPlaceHolders.aspx根目錄。 Visual Web 開發人員會使用下列宣告式標記來建立此頁面:

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

在參考 MainContent ContentPlaceHolders () Content2 的內容控件中輸入一些內容。 接下來,將下列標記新增至 Content3 [內容] 控件 (,以參考 LeftColumnContent ContentPlaceHolder) :

<h3>Page-Specific Content</h3>
<ul>
 <li>This content is defined in the content page.</li>
 <li>The master page has two regions in the Web Form that are editable on a
 page-by-page basis.</li>
</ul>

新增此標記之後,請瀏覽透過瀏覽器的頁面。 如圖 3 所示,放置於 [內容] 控件中的 Content3 標記會顯示在 [新聞] 區段下方的左側數據行中, (以紅色) 圓圈。 放置在 中的 Content2 標記會顯示在頁面的右部分, (以藍色) 圓圈。

左欄現在包含新聞區段下方 Page-Specific 內容

圖 03:左欄現在包含 [新聞] 區段下方的 [Page-Specific 內容], (按兩下即可檢視完整大小的影像)

在現有內容頁面中定義內容

建立新的內容頁面會自動納入我們在步驟 1 中新增的 ContentPlaceHolder 控件。 但我們的兩個現有內容頁面 - About.aspxDefault.aspx - 沒有 ContentPlaceHolder 的內容控制件 LeftColumnContent 。 若要在這兩個現有頁面中指定此 ContentPlaceHolder 的內容,我們必須自行新增 Content 控件。

不同於大部分 ASP.NET Web 控制件,Visual Web 開發人員工具箱不包含內容控制項專案。 我們可以在 [來源] 檢視中手動輸入內容控制件的宣告式標記,但較簡單且更快速的方法就是使用 [設計] 檢視。 About.aspx開啟頁面並切換至 [設計] 檢視。 如圖 4 所示, LeftColumnContent ContentPlaceHolder 會出現在 [設計] 檢視中;如果您將滑鼠移至該檢視上,顯示的標題會顯示:「LeftColumnContent (Master) 」。標題中包含 「Master」 表示此 ContentPlaceHolder 頁面中沒有定義任何內容控制件。 如果 ContentPlaceHolder 的內容控制件存在,如 的案例 MainContent所示,標題會讀取:「ContentPlaceHolderID (自定義) 」。

若要將 ContentPlaceHolder 的內容控件 LeftColumnContent 新增至 About.aspx,請展開 ContentPlaceHolder 的智慧標記,然後按兩下 [建立自定義內容] 連結。

About.aspx的設計視圖顯示 LeftColumnContent ContentPlaceHolder

圖 04:顯示 LeftColumnContent ContentPlaceHolder 的設計檢視 About.aspx (按兩下即可檢視完整大小的影像)

點選 「建立自訂內容」 連結會在頁面中產生必要的 [內容] 控制件,並將其 屬性設定 ContentPlaceHolderID 為 ContentPlaceHolder 的 ID。 例如,按兩下列的About.aspxLeftColumnContent建立自訂內容】 連結,會將下列宣告式標記新增至頁面:

<asp:Content ID="Content3" runat="server" contentplaceholderid="LeftColumnContent">
 
</asp:Content>

省略內容控制件

ASP.NET 不需要所有內容頁面都包含主版頁面中定義的每個 ContentPlaceHolder 內容控制件。 如果省略 Content 控件,ASP.NET 引擎會使用主版頁面中 ContentPlaceHolder 內定義的標記。 此標記稱為 ContentPlaceHolder 的預設內容 ,而且在某些區域的內容在大部分頁面之間很常見,但需要針對少數頁面自定義的案例中很有用。 步驟 3 會探索在主版頁面中指定預設內容。

目前,Default.aspx包含和 MainContent ContentPlaceHolders 的兩個 Content 控件head;它沒有 的 LeftColumnContentContent 控件。 因此,當 轉譯時 Default.aspxLeftColumnContent 會使用 ContentPlaceHolder 的預設內容。 因為我們尚未為此 ContentPlaceHolder 定義任何預設內容,所以淨效果是此區域不會發出任何標記。 若要確認此行為,請瀏覽 Default.aspx 瀏覽器。 如圖 5 所示,在 [新聞] 區段下方的左欄中不會發出任何標記。

LeftColumnContent ContentPlaceHolder 不會轉譯任何內容

圖 05:未針對 LeftColumnContent ContentPlaceHolder 轉譯任何內容 (按兩下即可檢視完整大小的影像)

步驟 3:在主版頁面中指定預設內容

某些網站設計包含一個區域,其內容與網站中的所有頁面相同,但有一或兩個例外狀況除外。 請考慮支援用戶帳戶的網站。 這類網站需要登入頁面,訪客可以在其中輸入其認證來登入網站。 為了加速登入程式,網站設計工具可能包含每個頁面左上角的使用者名稱和密碼文本框,讓使用者不需要明確流覽登入頁面。 雖然這些使用者名稱和密碼文本框在大部分頁面中都很有用,但它們在登入頁面中是多餘的,其中已經包含使用者認證的文本框。

若要實作此設計,您可以在主版頁面左上角建立 ContentPlaceHolder 控件。 每個需要在其左上角顯示使用者名稱和密碼文本框的頁面,都會為此 ContentPlaceHolder 建立內容控制件,並新增必要的介面。 另一方面,登入頁面會省略為此 ContentPlaceHolder 新增 Content 控件,或建立未定義標記的內容控件。 此方法的缺點是,我們必須記得將使用者名稱和密碼文本框新增至我們新增至網站的每個頁面 (,但登入頁面除外) 。 這會要求發生問題。 我們可能會忘記將這些文本框新增至頁面或兩個或更糟的是,我們可能不會正確地實作介面, (可能只新增一個文本框,而不是兩個) 。

更好的解決方案是將使用者名稱和密碼文本框定義為 ContentPlaceHolder 的預設內容。 如此一來,我們只需要在未 (登入頁面顯示使用者名稱和密碼文本框的幾個頁面中覆寫此默認內容,例如) 。 為了說明如何指定 ContentPlaceHolder 控件的預設內容,讓我們實作剛才討論的案例。

注意

本教學課程的其餘部分會更新我們的網站,以包含所有頁面但登入頁面的左側數據行中的登入介面。 不過,本教學課程不會檢查如何設定網站以支援用戶帳戶。 如需本主題的詳細資訊,請參閱我的 窗體驗證、授權、用戶帳戶和角色 教學課程。

新增 ContentPlaceHolder 並指定其預設內容

Site.master開啟主版頁面,並將下列標記新增至標籤與 Lessons 區段之間的DateDisplay左欄:

<asp:ContentPlaceHolder ID="QuickLoginUI" runat="server">
 <asp:Login ID="QuickLogin" runat="server" 
    TitleText="<h3>Sign In</h3>"
    FailureAction="RedirectToLoginPage">
 </asp:Login>
</asp:ContentPlaceHolder>

新增此標記之後,主版頁面的設計檢視看起來應該類似圖 6。

主版頁面包含登入控件

圖 06:主版頁面包含登入控件 (按鍵即可檢視完整大小的影像)

此 ContentPlaceHolder QuickLoginUI具有 Login Web 控件作為其預設內容。 [登入] 控制項會顯示使用者介面,提示使用者輸入其使用者名稱和密碼,以及 [登入] 按鈕。 按兩下 [登入] 按鈕時,登入控件會在內部根據成員資格 API 驗證使用者的認證。 若要在實務上使用此登入控件,您必須將網站設定為使用成員資格。 本主題超出本教學課程的範圍;如需建置支援使用者帳戶的 Web 應用程式的詳細資訊,請參閱我的 窗體驗證、授權、用戶帳戶和角色 教學課程。

您可以隨意自定義登入控件的行為或外觀。 我已設定其兩個屬性: TitleTextFailureActionTitleText預設值為 「登入」的屬性值會顯示在控件的使用者介面頂端。 我已設定這個屬性,讓它將文字 「登入」顯示為 <h3> 元素。 屬性 FailureAction 表示如果使用者的認證無效,該怎麼辦。 它預設為的值 Refresh,這會在相同的頁面上留下使用者,並在登入控件內顯示失敗訊息。 我已將其變更為 RedirectToLoginPage,這會在認證無效時將用戶傳送至登入頁面。 我偏好在用戶嘗試從其他頁面登入時,將用戶傳送至登入頁面,但失敗,因為登入頁面可以包含其他指示和選項,而無法輕易放入左側數據行。 例如,登入頁面可能包含用來擷取忘記密碼或建立新帳戶的選項。

建立登入頁面並覆寫默認內容

完成主版頁面之後,下一個步驟是建立登入頁面。 將 ASP.NET 頁面新增至網站根目錄, Login.aspx並將它系結至 Site.master 主版頁面。 這麼做會建立具有四個 Content 控件的頁面,其中一個用於 中 Site.master定義的 ContentPlaceHolders。

將 [登入] 控件新增至 MainContent [內容] 控制件。 同樣地,您可以隨意將任何內容新增至 LeftColumnContent 區域。 不過,請務必將 ContentPlaceHolder 的內容 QuickLoginUI 控件保留空白。 這可確保 [登入] 控件不會出現在登入頁面的左欄中。

定義 和 LeftColumnContent 區域的內容MainContent之後,登入頁面的宣告式標記看起來應該如下所示:

<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Login.aspx.cs" Inherits="Login" Title="Untitled Page" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server">
 <h2>
 Sign In</h2>
 <p>
 <asp:Login ID="Login1" runat="server" TitleText="">
 </asp:Login>
 </p>
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="QuickLoginUI" Runat="Server">
</asp:Content>
<asp:Content ID="Content4" ContentPlaceHolderID="LeftColumnContent" Runat="Server">
 <h3>Sign In Tasks</h3>
 <ul>
 <li>Create a New Account</li>
 <li>Recover Forgotten Password</li>
 </ul>
 <p>TODO: Turn the above text into links...</p>
</asp:Content>

圖 7 顯示透過瀏覽器檢視此頁面。 因為此頁面會指定 ContentPlaceHolder 的內容 QuickLoginUI 控制件,所以它會覆寫主版頁面中指定的預設內容。 淨效果是主版頁面的 [設計] 檢視中顯示的 [登入] 控件, (請參閱此頁面中未轉譯圖 6) 。

登入頁面會重新壓縮 QuickLoginUI ContentPlaceHolder 的預設內容

圖 07:登入頁面會壓縮 QuickLoginUI ContentPlaceHolder 的預設內容 (按兩下即可檢視大小完整的影像)

在新頁面中使用預設內容

我們想要在所有頁面的左欄中顯示 Login 控件,但 [登入] 頁面除外。 若要達成此目的,除了登入頁面以外的所有內容頁面,都應該省略 ContentPlaceHolder 的內容 QuickLoginUI 控制件。 藉由省略內容控件,將會改用 ContentPlaceHolder 的預設內容。

我們現有的內容頁面 - Default.aspxAbout.aspxMultipleContentPlaceHolders.aspx - 不包含 的內容控制件,因為它們是在將 ContentPlaceHolder 控制件 QuickLoginUI 新增至主版頁面之前建立的。 因此,這些現有的頁面不需要更新。 不過,新增至網站的新頁面預設會包含 ContentPlaceHolder 的內容 QuickLoginUI 控制件。 因此,我們必須記得在每次新增內容頁面 (移除這些內容控件,除非我們想要覆寫 ContentPlaceHolder 的默認內容,如登入頁面) 的情況。

若要移除內容控制件,您可以從 [來源] 檢視手動刪除其宣告式標記,或從 [設計] 檢視中選擇 [主圖形的內容預設值] 連結。 任一種方法會從頁面移除內容控制件,並產生相同的凈效果。

圖 8 顯示 Default.aspx 透過瀏覽器檢視時。 回想一下, Default.aspx 其宣告式標記中只指定兩個 Content 控件,一個用於 head ,一個用於 MainContent。 因此,會顯示 和 QuickLoginUI ContentPlaceHolders 的預設內容LeftColumnContent

LeftColumnContent 和 QuickLoginUI ContentPlaceHolders 的預設內容隨即顯示

圖 08:和 QuickLoginUI ContentPlaceHolders 的預設內容LeftColumnContent會顯示 (按兩下即可檢視大小完整的影像)

摘要

ASP.NET 主版頁面模型允許主版頁面中任意數目的 ContentPlaceHolders。 此外,ContentPlaceHolders 包含預設內容,這會在內容頁面中沒有對應的內容控件時發出。 在本教學課程中,我們已瞭解如何在主版頁面中包含其他 ContentPlaceHolder 控件,以及如何在新的和現有的 ASP.NET 頁面中定義這些新 ContentPlaceHolders 的內容控件。 我們也探討在 ContentPlaceHolder 中指定預設內容,這在只有少數頁面需要自定義特定區域內的標準化內容的情況下很有用。

在下一個教學課程中,我們將更詳細地檢查 head ContentPlaceHolder,瞭解如何以宣告方式和以程式設計方式定義逐頁的標題、中繼標記和其他 HTML 標頭。

快樂的程序設計!

關於作者

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放在 。