マスターページのContentPlaceHolderコントロールでデフォルトコンテンツを提供しよう
マスターページでは、どのコンテンツページでも変化しないマークアップと共に、ページ単位でカスタマイズ可能な領域も定義します。コンテンツページごとにカスタマイズ可能な領域を指示するにはContentPlaceHolderコントロールを使います。マスターページにはこのコントロールをいくつでも含めることができます。サイトに新しいコンテンツページを追加すると、マスターページで定義した各ContentPlaceHolderのコンテンツページにコンテンツコントロールが追加され、(ページ開発者が)各領域にページ固有のコンテンツを定義するよう促されます。
実は、これらのコンテンツコントロールをコンテンツページで使わなくてもかまいません。コンテンツページでContentPlaceHolderのコンテンツコントロールを定義しなければならないのは、カスタムコンテンツを提供する場合だけです。さらに、マスターページ内のContentPlaceHolderコントロールにもコンテンツを含めることができ、それをオーバーライドするコンテンツコントロールをコンテンツページで提供しなければ、それがデフォルトのコンテンツとして使用されます。
上の最後の説明は「コンテンツ」という語が9回も出てくるので少し分かりにくいかもしれません。簡単な例で説明しましょう。今、マスターページにFirstContentPlaceHolderとSecondContentPlaceHolderという2つのContentPlaceHolderコントロールがあるものとします。通常、ContentPlaceHolderコントロールは、次のように内部にコンテンツを指定しないで定義します。
<%@ Master Language="VB" CodeFile="Site.master.vb" Inherits="Site" %> ... Some markup removed for brevity ... <asp:ContentPlaceHolder id="FirstContentPlaceHolder" runat="server"> </asp:ContentPlaceHolder> <p>Blah blah blah</p> <asp:ContentPlaceHolder id="SecondContentPlaceHolder" runat="server"> </asp:ContentPlaceHolder>
つまり、コンテンツページで2つのコンテンツコントロールを定義し、そこでこれらの領域についてページ固有のコンテンツを定義するわけです。例えば、コンテンツページに次のマークアップが含まれているものとします。
<%@ Page Title="" Language="VB" MasterPageFile="~/Site.master" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %> <asp:Content ID="Content1" ContentPlaceHolderID="FirstContentPlaceHolder" Runat="Server"> I have nothing interesting to say. </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="SecondContentPlaceHolder" Runat="Server"> I should start a blog! </asp:Content>
Content1とContent2の2つのコンテンツコントロールがあり、そこで定義されたコンテンツが、それぞれマスターページのFirstContentPlaceHolderとSecondContentPlaceHolderというContentPlaceHolderコントロールに注入されることに注意してください。このコンテンツページをブラウザで表示すると、図1のようになります。

しかし、マスターページに手を加えれば、これら2つのContentPlaceHolderのデフォルトコンテンツを定義できます。例えば、変更後のマスターページは次のようになります。
<%@ Master Language="VB" CodeFile="Site.master.vb" Inherits="Site" %> ... Some markup removed for brevity ... <asp:ContentPlaceHolder id="FirstContentPlaceHolder" runat="server"> <h1>This is the first content place holder!</h1> </asp:ContentPlaceHolder> <p>Blah blah blah</p> <asp:ContentPlaceHolder id="SecondContentPlaceHolder" runat="server"> <h1>This is the second content place holder!</h1> </asp:ContentPlaceHolder>
このコンテンツページをブラウザで再度表示すると、上と同じ画面が表示されます。しかし、いずれかのコンテンツコントロールをコンテンツページから削除すると、新しい表示は対応するContentPlaceHolderで定義されているデフォルトコンテンツに置き換えられます。例えば、SecondContentPlaceHolderというContentPlaceHolderを参照するContent2コンテンツコントロールを削除した場合、コンテンツページのマークアップは次のようになります。
<%@ Page Title="" Language="VB" MasterPageFile="~/Site.master" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %> <asp:Content ID="Content1" ContentPlaceHolderID="FirstContentPlaceHolder" Runat="Server"> I have nothing interesting to say. </asp:Content>
こうした上で同じページをブラウザで開くと、コンテンツページで定義したコンテンツ("I have nothing interesting to say")がページの最初に表示され、SecondContentPlaceHolder、ContentPlaceHolderについてはデフォルトのマークアップ("This is the second content place holder!")が表示されます。このコンテンツページをブラウザで表示すると、図2のようになります。

ContentPlaceHolderコントロールのこのデフォルトマークアップ機能は、サイトのある特定の領域のコンテンツがほぼすべてのページで変化しないのに、その同じ領域のコンテンツを他の1ページか2ページでカスタマイズしなければならないような状況で役に立ちます。この場合は次の作業を行います。
- マスターページに
ContentPlaceHolderを追加することで、大部分のページでは変化しないが一部のページでカスタマイズしなければならない領域を指示する。 - 大部分のページに共通するマークアップを
ContentPlaceHolder内に入力する。 - 同じデフォルトコンテンツを使用するASP.NETページで、対応するコンテンツコントロールをページのマークアップから削除する。
- 固有のコンテンツを持つページについて、対応するコンテンツコントロールを作成し、その内部に固有のコンテンツを定義する。
このテクニックの詳細については、「Multiple ContentPlaceHolders and Default Content」というチュートリアルを参照ください。これはThe Official Microsoft ASP.NET Siteで私が公開している10件のマスターページに関するチュートリアル(Master Page Tutorials)の1つです。
