在 ASP.NET Web Pages (Razor) 網站中建立一致的版面配置

作者:Tom FitzMacken

本文說明如何使用 ASP.NET Web Pages (Razor) 網站中的版面配置頁面,建立可重複使用的內容區塊 (,例如頁首和頁尾) ,以及建立網站中所有頁面的一致外觀。

您將瞭解的內容:

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

以下是文章仲介紹的 ASP.NET 功能:

  • 內容區塊,這些檔案包含要插入多個頁面的 HTML 格式內容。
  • 版面配置頁面,這些頁面包含可由網站上的頁面共用的 HTML 格式內容。
  • RenderPageRenderBodyRenderSection 方法,可告訴 ASP.NET 要插入頁面元素的位置。
  • PageData字典,可讓您在內容區塊和版面配置頁面之間共用資料。

教學課程中使用的軟體版本

  • ASP.NET Web Pages (Razor) 3

本教學課程也適用于 ASP.NET Web Pages 2。

關於版面配置頁面

許多網站都有顯示于每個頁面上的內容,例如頁首和頁尾,或告知使用者登入的方塊。 ASP.NET 可讓您建立包含文字、標記和程式碼之內容區塊的個別檔案,就像一般網頁一樣。 然後,您可以將內容區塊插入網站中您想要顯示資訊的其他頁面中。 如此一來,您就不需要將相同的內容複寫並貼到每個頁面中。 建立類似這樣的常見內容,也可讓您更輕鬆地更新您的網站。 如果您需要變更內容,您可以只更新單一檔案,然後變更就會反映在內容插入的任何地方。

下圖顯示內容區塊的運作方式。 當瀏覽器向網頁伺服器要求頁面時,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 的 [ 檔案 ] 工作區中,以滑鼠右鍵按一下檔案,然後選取 [ 在 browser 中啟動]。)

  9. 在瀏覽器中,檢視頁面來源。 (例如,在 Internet Explorer 中,以滑鼠右鍵按一下頁面,然後按一下 [ 檢視 Source.)

    這可讓您查看傳送至瀏覽器的網頁標記,這會結合索引頁標記與內容區塊。 下列範例顯示針對 Index.cshtml轉譯的頁面來源。 您插入Index.cshtml的呼叫 RenderPage 已取代為頁首和頁尾檔案的實際內容。

    <!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. [樣式] 資料夾中,建立名為 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中定義的 (內容) 文字。

    [此螢幕擷取畫面顯示在瀏覽器中執行內容 1 點 CSHTML。]

    您可以重複步驟 6 來建立其他內容頁面,然後共用相同的版面配置頁面。

    注意

    您可以設定您的網站,以便自動針對資料夾中的所有內容頁面使用相同的版面配置頁面。 如需詳細資訊,請參閱自訂 ASP.NET Web PagesSite-Wide行為

設計具有多個內容區段的配置頁面

內容頁面可以有多個區段,如果您想要使用具有多個區域且可取代內容的版面配置,這非常有用。 在內容頁面中,您會為每個區段提供唯一的名稱。 (預設區段保持未命名。) 在版面配置頁面中,您可以新增 RenderBody 方法來指定未命名 (預設) 區段應該會出現的位置。 然後,您可以新增個別 RenderSection 的方法,以便個別轉譯具名區段。

下圖顯示 ASP.NET 如何處理分成多個區段的內容。 每個具名區段都包含在內容頁面中的區段區塊中。 (它們命名 Header 為 ,並在 List example.) 架構會將內容區段插入配置頁面的呼叫點 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. [共用資料夾 ] 中,開啟 _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 屬性取得標題值。 它也會使用 ShowList 屬性的值 PageData 來判斷是否要顯示清單內容區塊。

  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 Web Pages的Site-Wide行為