共用方式為


在 ASP.NET 網頁 (Razor) 網站中建立一致的佈局

演講者:Tom FitzMacken

本文介紹如何在 ASP.NET 網頁 (Razor) 網站中使用佈局頁面來建立可重複使用的內容區塊 (如頁首和頁尾),並為網站中的所有頁面建立一致的外觀。

您將學到什麼:

  • 如何建立可重複使用的內容區塊,例如頁首和頁尾。
  • 如何使用佈局為網站中的所有頁面建立一致的外觀。
  • 如何在執行時將資料傳遞到佈局頁面。

這些就是本文介紹的 ASP.NET 功能:

  • 內容區塊,是包含要插入多個頁面的 HTML 格式內容的檔案。
  • 版面設定頁面,是包含可被網站上的頁面分享的 HTML 格式內容的頁面。
  • RenderPageRenderBodyRenderSection 方法,告訴 ASP.NET 在哪裡插入頁面元素。
  • 允許您在內容區塊和版面設定頁面之間共用資料的 PageData 字典。

教學中使用的軟體版本

  • ASP.NET 網頁 (Razor) 3

本教學也適用於 ASP.NET 網頁 2。

關於佈局頁面

許多網站的每個頁面上都會顯示內容,例如頁首和頁腳,或告訴使用者他們已登入的框框。 ASP.NET 可讓您建立一個帶有內容區塊的單獨文件,該內容區塊可以包含文字、標記和程式碼,就像常規網頁一樣。 然後,您可以將內容區塊插入網站上希望顯示資訊的其他頁面中。 這樣您就不必將相同的內容複製並貼上到每個頁面中。 建立像這樣的常見內容還可以更輕鬆地更新您的網站。 如果您需要更改內容,只需更新單個文件,然後更改就會反映到插入內容的所有位置。

下圖顯示了內容區塊的工作原理。 當瀏覽器從 Web 伺服器請求頁面時,ASP.NET 會在主頁中呼叫 RenderPage 方法的位置插入內容塊。 然後將完成 (合併) 的頁面傳送到瀏覽器。

顯示 RenderPage 方法如何將引用的頁面插入目前頁面的概念圖。

在此過程中,您將建立一個引用位於不同文件中的兩個內容區塊 (頁首和頁尾) 的頁面。 您可以在網站的任何頁面中使用這些相同的內容區塊。 完成後,您將看到如下頁面:

顯示瀏覽器中執行包含對 RenderPage 方法的呼叫的頁面所產生的頁面的螢幕截圖。

  1. 在網站的根資料夾中,建立一個名為 Index.cshtml 的檔案。

  2. 將現有標記替換為以下內容:

    <!DOCTYPE html>
    <html>
      <head>
        <title>Main Page</title>
      </head>
      <body>
    
        <h1>Index Page Content</h1>
        <p>This is the content of the main page.</p>
    
      </body>
    </html>
    
  3. 在根資料夾中,建立一個名為 Shared 的資料夾。

    注意

    通常的做法是將網頁之間共享的檔案儲存在名為 Shared 的資料夾中。

  4. 共用資料夾中,建立一個名為 _Header.cshtml 的檔案。

  5. 將任何現有內容替換為以下內容:

    <div class="header">This is header text.</div>
    

    請注意,檔案名稱是 _Header.cshtml,以下劃線 (_) 作為前綴。 如果頁面名稱以下劃線開頭,ASP.NET 不會將頁面傳送到瀏覽器。 這可以防止人們直接要求 (無意或其他方式) 這些頁面。 使用下劃線來命名其中包含內容區塊的頁面是一個好主意,因為您實際上並不希望用戶能夠請求這些頁面 - 它們的存在嚴格是為了插入其他頁面。

  6. 共用資料夾中,建立一個名為 _Footer.cshtml 的檔案並將內容替換為以下內容:

    <div class="footer">&copy; 2012 Contoso Pharmaceuticals. All rights reserved.
    </div>
    
  7. Index.cshtml 頁面中,新增兩個對 RenderPage 方法的調用,如下所示:

    <!DOCTYPE html>
    <html>
      <head>
        <title>Main Page</title>
      </head>
      <body>
    
        @RenderPage("~/Shared/_Header.cshtml")
    
        <h1>Index Page Content</h1>
        <p>This is the content of the main page.</p>
    
        @RenderPage("~/Shared/_Footer.cshtml")
    
      </body>
    </html>
    

    這展示瞭如何將內容區塊插入網頁中。 您呼叫 RenderPage 方法並向其傳遞要在此時插入其內容的檔案的名稱。 在這裡,您將 _Header.cshtml_Footer.cshtml 檔案的內容插入到 Index.cshtml 檔案中。

  8. 在瀏覽器中執行 Index.cshtml 頁面。 (在 WebMatrix 的檔案工作區中,右鍵點擊該文件,然後選擇在瀏覽器中啟動。)

  9. 在瀏覽器中,查看頁面原始碼。 (例如,在 Internet Explorer 中,右鍵按一下該頁面,然後按一下檢視原始碼。)

    這使您可以查看發送到瀏覽器的網頁標記,該標記將索引頁標記與內容區塊組合在一起。 以下範例顯示了為 Index.cshtml 呈現的頁面來源。 對插入 RenderPageIndex.cshtml 的呼叫已替換為頁首和頁尾檔案的實際內容。

    <!DOCTYPE html>
    <html>
      <head>
        <title>Main Page</title>
      </head>
      <body>
    
      <div class="header">
        This is header text.
      </div>
    
        <h1>Index Page Content</h1>
        <p>This is the content of the main page.</p>
    
      <div class="footer">
        &copy; 2012 Contoso Pharmaceuticals. All rights reserved.
      </div>
    
      </body>
    </html>
    

使用佈局頁面建立一致的外觀

到目前為止,您已經看到在多個頁面上包含相同的內容是很容易的。 建立一致的網站外觀的一種更結構化的方法是使用佈局頁面。 佈局頁面定義網頁的結構,但不包含任何實際內容。 建立佈局頁面後,您可以建立包含內容的網頁,然後將它們連結到佈局頁面。 當這些頁面顯示時,它們將根據佈局頁面進行格式化。 (從這個意義上說,佈局頁面充當其他頁面中定義的內容的一種範本。)

佈局頁面就像任何 HTML 頁面一樣,只是它包含對 RenderBody 方法的呼叫。 RenderBody 方法在佈局頁面中的位置決定了內容頁面中的資訊將包含在何處。

下圖顯示如何在執行時間組合內容頁面和佈局頁面以產生最終的網頁。 瀏覽器請求內容頁。 內容頁面中包含指定用於頁面結構的佈局頁面的程式碼。 在佈局頁面中,內容被插入到呼叫 RenderBody 方法的位置。 也可以透過呼叫 RenderPage 方法將內容區塊插入到佈局頁面中,就像您在上一節中所做的那樣。 當網頁完成後,它會被發送到瀏覽器。

顯示瀏覽器中執行包含對 RenderBody 方法的呼叫的頁面所產生的頁面的螢幕截圖。

以下過程顯示如何建立佈局頁面並將內容頁面連結到它。

  1. 在網站的共用資料夾中,建立一個名為 _Layout1.cshtml 的檔案。

  2. 將任何現有內容替換為以下內容:

    <!DOCTYPE html>
    <html>
      <head>
        <title>Structured Content </title>
        <link href="~/Styles/Site.css" rel="stylesheet" type="text/css" />
      </head>
      <body>
        @RenderPage("~/Shared/_Header2.cshtml")
        <div id="main">
          @RenderBody()
        </div>
        <div id="footer">
          &copy; 2012 Contoso Pharmaceuticals. All rights reserved.
        </div>
      </body>
    </html>
    

    您可以在佈局頁面中使用 RenderPage 方法來插入內容區塊。 佈局頁面只能包含對 RenderBody 方法的一次呼叫。

  3. 共用資料夾中,建立一個名為 _Header2.cshtml 的文件,並將任何現有內容替換為以下內容:

    <div id="header">Creating a Consistent Look</div>
    
  4. 在根資料夾中,建立一個新資料夾並將其命名為 Styles

  5. Styles 資料夾中,建立一個名為 Site.css 的檔案並新增以下樣式定義:

    h1 {
        border-bottom: 3px solid #cc9900;
        font: 2.75em/1.75em Georgia, serif;
        color: #996600;
    }
    
    ul {
        list-style-type: none;
    }
    
    body {
        margin: 0;
        padding: 1em;
        background-color: #ffffff;
        font: 75%/1.75em "Trebuchet MS", Verdana, sans-serif;
        color: #006600;
    }
    
    #list {
        margin: 1em 0 7em -3em;
        padding: 1em 0 0 0;
        background-color: #ffffff;
        color: #996600;
        width: 25%;
        float: left;
    }
    
    #header, #footer {
        margin: 0;
        padding: 0;
        color: #996600;
    }
    

    這些樣式定義僅用於顯示樣式表如何與版面設定頁面一起使用。 如果需要,您可以為這些元素定義自己的樣式。

  6. 在根資料夾中,建立一個名為 Content1.cshtml 的檔案,並將任何現有內容替換為以下內容:

    @{
        Layout = "~/Shared/_Layout1.cshtml";
    }
    
    <h1> Structured Content </h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit,
    sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
    Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
    nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
    reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
    pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
    culpa qui officia deserunt mollit anim id est laborum.</p>
    

    這是一個將使用佈局頁面的頁面。 頁面頂部的程式碼區塊指示使用哪個佈局頁面來格式化此內容。

  7. 在瀏覽器中執行 Content1.cshtml。 呈現的頁面使用 _Layout1.cshtml 中定義的格式和樣式表以及 Content1.cshtml 中定義的文字 (內容)。

    [螢幕截圖顯示在瀏覽器中執行 Content 1 dot CSHTML。]

    您可以重複步驟 6 建立其他內容頁面,然後分享相同的版面頁面。

    注意

    您可以設定站點,以便可以自動對資料夾中的所有內容頁面使用相同的佈局頁面。 有關詳細資訊,請參閱自訂 ASP.NET 網頁的網站範圍行為

設計具有多個內容部分的佈局頁面

內容頁面可以有多個部分,如果您想使用具有多個可替換內容區域的佈局,這會很有用。 在內容頁面中,您為每個部分指定一個唯一的名稱。 (預設部分未命名。) 在版面設定頁面中,您會新增 RenderBody 方法來指定未命名 (預設) 部分應出現的位置。 然後,您新增單獨的 RenderSection 方法以單獨呈現命名部分。

下圖顯示了 ASP.NET 如何處理分為多個部分的內容。 每個命名部分都包含在內容頁的一個部分區塊中。 (在範例中它們被命名為 HeaderList。) 架構將內容部分插入佈局頁面中呼叫 RenderSection 方法的位置。 未命名 (預設) 部分將插入到呼叫 RenderBody 方法的位置,如您之前所見。

顯示 RenderSection 方法如何將引用部分插入目前頁面的概念圖。

此流程示範如何建立具有多個內容部分的內容頁面以及如何使用支援多個內容部分的佈局頁面呈現它。

  1. 共用資料夾中,建立一個名為 _Layout2.cshtml 的檔案。

  2. 將任何現有內容替換為以下內容:

    <!DOCTYPE html>
    <html>
      <head>
        <title>Multisection Content</title>
        <link href="~/Styles/Site.css" rel="stylesheet" type="text/css" />
      </head>
      <body>
        <div id="header">
          @RenderSection("header")
        </div>
        <div id="list">
          @RenderSection("list")
        </div>
        <div id="main">
          @RenderBody()
        </div>
        <div id="footer">
          &copy; 2012 Contoso Pharmaceuticals. All rights reserved.
        </div>
      </body>
    </html>
    

    您可以使用 RenderSection 方法來呈現標題和清單部分。

  3. 在根資料夾中,建立一個名為 Content2.cshtml 的文件,並將任何現有內容替換為以下內容:

    @{
        Layout = "~/Shared/_Layout2.cshtml";
    }
    
    @section header {
        <div id="header">
            Creating a Consistent Look
        </div>
    }
    
    @section list {
        <ul>
            <li>Lorem</li>
            <li>Ipsum</li>
            <li>Dolor</li>
            <li>Consecte</li>
            <li>Eiusmod</li>
            <li>Tempor</li>
            <li>Incididu</li>
        </ul>
    }
    
    <h1>Multisection Content</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit,
    sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
    Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
    nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
    reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
    pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
    culpa qui officia deserunt mollit anim id est laborum.</p>
    

    此內容頁面在頁面頂部包含一個程式碼區塊。 每個命名節都包含在一個節塊中。 頁面的其餘部分包含預設 (未命名) 內容部分。

  4. 在瀏覽器中執行 Content2.cshtml

    顯示瀏覽器中透過執行包含對 RenderSection 方法的呼叫的頁面而產生的頁面的螢幕截圖。

使內容部分可選

通常,您在內容頁面中建立的部分必須與佈局頁面中定義的部分相符。 如果發生以下任一情況,您可能會收到錯誤訊息:

  • 內容頁面包含一個在佈局頁面中沒有對應部分的部分。
  • 佈局頁面包含沒有內容的部分。
  • 佈局頁面包含嘗試多次呈現相同部分的方法呼叫。

但是,您可以透過在佈局頁面中將該部分聲明為可選來覆寫指定部分的此行為。 這使您可以定義多個內容頁面,這些頁面可以共用佈局頁面,但可能包含或不包含特定部分的內容。

  1. 打開 Content2.cshtml 並刪除以下部分:

    @section header {
      <div id="header">
        Creating a Consistent Look
      </div>
    }
    
  2. 儲存頁面,然後在瀏覽器中執行它。 將顯示錯誤訊息,因為內容頁不提供版面設定頁中定義的部分 (即標題部分) 的內容。

    顯示如果執行呼叫 RenderSection 方法的頁面但未提供對應部分時發生的錯誤的螢幕截圖。

  3. Shared 資料夾中,開啟 _Layout2.cshtml 頁面並替換此行:

    @RenderSection("header")
    

    使用下列程式碼:

    @RenderSection("header", required: false)
    

    作為替代方案,您可以將上一行程式碼替換為以下程式碼區塊,這會產生相同的結果:

    @if (IsSectionDefined("header")) {
        @RenderSection("header")
    }
    
  4. 再次在瀏覽器中執行 Content2.cshtml 頁面。 (如果您仍然在瀏覽器中開啟此頁面,則只需重新整理即可。) 這次頁面顯示沒有錯誤,即使它沒有標題。

將資料傳遞到佈局頁面

您可能在內容頁面中定義了需要在版面設定頁面中引用的資料。 如果是這樣,您需要將資料從內容頁傳遞到佈局頁。 例如,您可能想要顯示使用者的登入狀態,或者您可能希望根據使用者輸入顯示或隱藏內容區域。

若要將資料從內容頁傳遞到版面頁,您可以將值放入內容頁的 PageData 屬性中。 PageData 屬性是名稱/值對的集合,用於保存要在頁面之間傳遞的資料。 在佈局頁面中,您可以從 PageData 屬性中讀取值。

這是另一張圖。 本節展示了 ASP.NET 如何使用 PageData 屬性將值從內容頁傳遞到版面設定頁。 當 ASP.NET 開始建立網頁時,它會建立 PageData 集合。 在內容頁面中,您編寫程式碼以將資料放入 PageData 集合中。 PageData 集合中的值也可以透過內容頁面中的其他部分或其他內容區塊存取。

顯示內容頁面如何填入 PageData 字典並將該資訊傳遞到版面設定頁面的概念圖。

以下流程顯示如何將資料從內容頁傳遞到版面設定頁。 當頁面執行時,它會顯示一個按鈕,讓使用者隱藏或顯示佈局頁面中定義的清單。 當使用者單擊該按鈕時,它會在 PageData 屬性中設定 true/false (布林) 值。 佈局頁面讀取該值,如果為 false,則隱藏該清單。 該值還在內容頁面中用於確定是顯示隱藏清單按鈕還是顯示清單按鈕。

[螢幕截圖顯示傳遞資料頁面。]

  1. 在根資料夾中,建立一個名為 Content3.cshtml 的文件,並將任何現有內容替換為以下內容:

    @{
        Layout = "~/Shared/_Layout3.cshtml";
    
        PageData["Title"] = "Passing Data";
        PageData["ShowList"] = true;
    
        if (IsPost) {
            if (Request.Form["list"] == "off") {
                PageData["ShowList"] = false;
            }
        }
    }
    
    @section header {
      <div id="header">
        Creating a Consistent Look
      </div>
    }
    
    <h1>@PageData["Title"]</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit,
    sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
    Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
    nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
    reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
    pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
    culpa qui officia deserunt mollit anim id est laborum.</p>
    
    @if (PageData["ShowList"] == true) {
        <form method="post" action="">
          <input type="hidden" name="list" value="off" />
          <input type="submit" value="Hide List" />
        </form>
    }
    else {
        <form method="post" action="">
          <input type="hidden" name="list" value="on" />
          <input type="submit" value="Show List" />
        </form>
    }
    

    程式碼在 PageData 屬性中儲存了兩個資料——網頁的標題和用於指定是否顯示清單的 true 或 false。

    請注意,ASP.NET 允許您使用程式碼區塊有條件地將 HTML 標記放入頁面中。 例如,頁面正文中的 if/else 區塊會根據 PageData["ShowList"] 是否設為 true 來決定顯示哪種表單。

  2. 共用資料夾中,建立一個名為 _Layout3.cshtml 的文件,並將任何現有內容替換為以下內容:

    <!DOCTYPE html>
    <html>
      <head>
        <title>@PageData["Title"]</title>
        <link href="~/Styles/Site.css" rel="stylesheet" type="text/css" />
      </head>
      <body>
        <div id="header">
          @RenderSection("header")
        </div>
          @if (PageData["ShowList"] == true) {
              <div id="list">
                @RenderPage("~/Shared/_List.cshtml")
              </div>
          }
        <div id="main">
          @RenderBody()
        </div>
        <div id="footer">
          <p>&copy; 2012 Contoso Pharmaceuticals. All rights reserved.</p>
        </div>
      </body>
    </html>
    

    版面設定頁面在 <title> 元素中包含一個從 PageData 屬性取得標題值的表達式。 它還使用 PageData 屬性的 ShowList 值來確定是否顯示清單內容區塊。

  3. 共用資料夾中,建立一個名為 _List.cshtml 的文件,並將任何現有內容替換為以下內容:

    <ul>
      <li>Lorem</li>
      <li>Ipsum</li>
      <li>Dolor</li>
      <li>Consecte</li>
      <li>Eiusmod</li>
      <li>Tempor</li>
      <li>Incididu</li>
    </ul>
    
  4. 在瀏覽器中執行 Content3.cshtml 頁面。 頁面顯示,清單在頁面左側可見,隱藏清單按鈕位於底部。

    顯示包含清單和「隱藏清單」按鈕的頁面的螢幕截圖。

  5. 點選隱藏清單。 該清單消失,按鈕變更為顯示清單

    顯示不包含清單的頁面和「顯示清單」按鈕的螢幕截圖。

  6. 按一下顯示清單按鈕,清單將再次顯示。

其他資源

自訂 ASP.NET 網頁的網站範圍行為