入れ子にされたマスター ページ (C#)

作成者: Scott Mitchell

あるマスター ページを別のマスター ページ内に入れ子にする方法を示します。

はじめに

過去 9 つのチュートリアルの過程で、マスター ページを含むサイト全体のレイアウトを実装する方法を見てきました。 簡単に言うと、マスター ページを使用すると、ページ開発者は、マスター ページ内の共通マークアップと、コンテンツ ページごとにカスタマイズできる特定の領域を定義できます。 マスター ページの ContentPlaceHolder コントロールは、カスタマイズ可能なリージョンを示します。ContentPlaceHolder コントロールのカスタマイズされたマークアップは、コンテンツ コントロールを使用してコンテンツ ページで定義されます。

これまでに調べてきたマスター ページの手法は、サイト全体で 1 つのレイアウトを使用している場合に最適です。 ただし、多くの大規模な Web サイトには、さまざまなセクションでカスタマイズされたサイト レイアウトがあります。 たとえば、病院のスタッフが患者の情報、アクティビティ、課金を管理するために使用する医療アプリケーションを考えてみましょう。 このアプリケーションには、次の 3 種類の Web ページがあります。

  • スタッフ メンバー固有のページ。スタッフ メンバーは、空き時間の更新、スケジュールの表示、休暇の要求を行うことができます。
  • スタッフ メンバーが特定の患者の情報を表示または編集する患者固有のページ。
  • 会計士が現在の請求状態と財務レポートを確認する課金固有のページ。

すべてのページで共通のレイアウトが共有される場合があります。たとえば、上部のメニューや、下部に沿ってよく使用される一連のリンクなどです。 ただし、スタッフ、患者、課金固有のページでは、この一般的なレイアウトをカスタマイズする必要がある場合があります。 たとえば、すべてのスタッフ固有のページには、現在ログオンしているユーザーの空き時間情報と毎日のスケジュールを示す予定表とタスク リストが含まれている必要があります。 おそらく、すべての患者固有のページでは、情報が編集されている患者の名前、住所、保険情報を表示する必要があります。

入れ子になったマスター ページを使用して、このようなカスタマイズされたレイアウトを作成できます。 上記のシナリオを実装するには、まず、サイト全体のレイアウト、メニュー、フッターのコンテンツを定義するマスター ページを作成し、ContentPlaceHolders でカスタマイズ可能な領域を定義します。 次に、入れ子になった 3 つのマスター ページ (Web ページの種類ごとに 1 つ) を作成します。 入れ子になった各マスター ページは、マスター ページを使用するコンテンツ ページの種類の間でコンテンツを定義します。 つまり、患者固有のコンテンツ ページの入れ子になったマスター ページには、編集中の患者に関する情報を表示するためのマークアップとプログラム ロジックが含まれます。 新しい患者固有のページを作成するときは、この入れ子になったマスター ページにバインドします。

このチュートリアルでは、まず、入れ子になったマスター ページの利点を強調します。 次に、入れ子になったマスター ページを作成して使用する方法を示します。

注意

入れ子になったマスター ページは、.NET Frameworkのバージョン 2.0 以降で可能です。 ただし、Visual Studio 2005 には、入れ子になったマスター ページのデザイン時のサポートは含まれていませんでした。 良いニュースは、Visual Studio 2008 では、入れ子になったマスター ページに豊富なデザイン時エクスペリエンスが提供されていることです。 入れ子になったマスター ページの使用に関心があるが、まだ Visual Studio 2005 を使用している場合は、Scott Guthrie のブログ エントリ「VS 2005 Design-Time の入れ子になったマスター ページのヒント」をチェックします。

入れ子になったマスター ページの利点

多くの Web サイトには、包括的なサイト デザインと、特定の種類のページに固有のカスタマイズされたデザインがあります。 たとえば、デモ Web アプリケーションでは、基本的な管理セクション (フォルダー内 ~/Admin のページ) を作成しました。 現在、フォルダー内の ~/Admin Web ページでは、管理セクションにないページと同じマスター ページが使用されます (つまり、 Site.masterAlternate.masterユーザーの選択に応じて )。

注意

ここでは、サイトにマスター ページが 1 つだけあるふりをします Site.master。 このチュートリアルで後述する「管理セクションに入れ子になったマスター ページを使用する」で始まる 2 つ以上のマスター ページを含む入れ子になったマスター ページの使用について説明します。

サイト内の他のページに存在しない追加情報やリンクを含むように、管理ページのレイアウトをカスタマイズするように求められたとします。 この要件を実装するには、次の 4 つの手法があります。

  1. 管理固有の情報とリンクをフォルダー内のすべてのコンテンツ ページに手動で ~/Admin 追加します。
  2. Site.master[管理] セクション固有の情報とリンクを含むようにマスター ページを更新し、いずれかの管理ページにアクセスしているかどうかに基づいて、これらのセクションを表示または非表示にするコードをマスター ページに追加します。
  3. [管理] セクション専用の新しいマスター ページを作成し、 から Site.masterマークアップをコピーし、 [管理] セクション固有の情報とリンクを追加し、この新しいマスター ページを使用するようにフォルダー内の ~/Admin コンテンツ ページを更新します。
  4. にバインド Site.master し、フォルダー内のコンテンツ ページでこの新しい入れ子になったマスター ページを使用する入れ子になったマスター ページを ~/Admin 作成します。 この入れ子になったマスター ページには、管理ページに固有の追加情報とリンクだけが含まれるので、 で Site.master既に定義されているマークアップを繰り返す必要はありません。

最初のオプションは、最も口当たりが低いオプションです。 マスター ページを使用する全体のポイントは、共通のマークアップを手動でコピーして新しい ASP.NET ページに貼り付ける必要がなくなる点です。 2 番目のオプションは受け入れられますが、場合によっては表示されるマークアップを使用してマスター ページを一括処理するため、アプリケーションの保守性が低下し、マスター ページを編集する開発者は、このマークアップを回避し、特定のマークアップが非表示の場合と正確にいつ表示されるかを覚えておく必要があります。 この方法は、この単一のマスター ページで対応する必要がある Web ページの種類が増えるにつれて、テナンシーが少なくなります。

3 番目のオプションでは、2 番目のオプションで表示される低優先メールと複雑さの問題を削除します。 ただし、オプション 3 のメイン欠点は、共通レイアウトSite.masterをコピーして新しい管理セクション固有のマスター ページに貼り付ける必要があるということです。 後でサイト全体のレイアウトを変更する場合は、忘れずに 2 か所で変更する必要があります。

4 番目のオプションである入れ子になったマスター ページは、2 番目と 3 番目のオプションのベストを提供します。 サイト全体のレイアウト情報は 1 つのファイル (最上位のマスター ページ) に保持されますが、特定のリージョンに固有のコンテンツは異なるファイルに分離されます。

このチュートリアルでは、まず、単純な入れ子になったマスター ページの作成と使用について説明します。 まったく新しい最上位マスター ページ、2 つの入れ子になったマスター ページ、2 つのコンテンツ ページを作成します。 「管理セクションに入れ子になったマスター ページを使用する」以降では、既存のマスター ページ アーキテクチャを更新して、入れ子になったマスター ページの使用を含めます。 具体的には、入れ子になったマスター ページを作成し、それを使用して、フォルダー内のコンテンツ ページの追加のカスタム コンテンツを ~/Admin 含めます。

手順 1: シンプルな Top-Level マスター ページを作成する

既存のマスター ページのいずれかに基づいて入れ子になったマスター シェイプを作成し、最上位マスター ページではなくこの新しい入れ子になったマスター ページを使用するように既存のコンテンツ ページを更新すると、既存のコンテンツ ページで最上位マスター ページで定義されている特定の ContentPlaceHolder コントロールが既に想定されているため、複雑さが伴います。 したがって、入れ子になったマスター ページには、同じ名前の同じ ContentPlaceHolder コントロールも含まれている必要があります。 さらに、特定のデモ アプリケーションには、ユーザーの設定に基づいてコンテンツ ページに動的に割り当てられる 2 つのマスター ページ (Site.masterAlternate.master) があり、この複雑さが増します。 このチュートリアルの後半で、入れ子になったマスター ページを使用するように既存のアプリケーションを更新する方法について説明しますが、最初に、入れ子になった単純なマスター ページの例に焦点を当ててみましょう。

という名前の新しいフォルダーを作成し、 という NestedMasterPages 名前 Simple.masterの新しいマスター ページ ファイルをそのフォルダーに追加します。 (このフォルダーとファイルが追加された後のソリューション エクスプローラーのスクリーン ショットについては、図 1 を参照してください)。スタイル シート ファイルをAlternateStyles.cssソリューション エクスプローラーからDesignerにドラッグします。 これにより、 <link> 要素内のスタイル シート ファイルに要素が <head> 追加され、その後、マスター ページの要素の <head> マークアップは次のようになります。

<head runat="server">
 <title>Untitled Page</title> 
 <asp:ContentPlaceHolder id="head" runat="server"> 
 </asp:ContentPlaceHolder>
 <link href="../AlternateStyles.css" rel="stylesheet" type="text/css" /> 
</head>

次に、 の Web フォーム内に次の Simple.masterマークアップを追加します。

<div id="topContent"> 
 <asp:HyperLink ID="lnkHome" runat="server" 
 NavigateUrl="~/NestedMasterPages/Default.aspx"
 Text="Nested Master Pages Tutorial (Simple)" /> 
</div> 
<div id="mainContent"> 
 <asp:ContentPlaceHolder id="MainContent" runat="server"> 
 </asp:ContentPlaceHolder>
</div>

このマークアップでは、ページの上部に "入れ子になったマスター ページ (Simple)" というタイトルのリンクが、ネイビーの背景に大きな白いフォントで表示されます。 その下に MainContent ContentPlaceHolder があります。 図 1 は、Simple.masterVisual Studio Designerに読み込まれたマスター ページを示しています。

Visual Studio Designerに読み込まれた場合の単純なドット マスター マスター ページ。

図 01: 入れ子になったマスター ページは、[管理] セクションのページに固有のコンテンツを定義します (フルサイズの画像を表示する をクリックします)。

手順 2: 単純な入れ子になったマスター ページを作成する

Simple.master には、2 つの ContentPlaceHolder コントロール MainContent が含まれています。Web フォーム内で追加した ContentPlaceHolder と、 要素の head<head> ContentPlaceHolder です。 コンテンツ ページを作成してコンテンツ ページに Simple.master バインドすると、2 つの ContentPlaceHolders を参照する 2 つの Content コントロールが含まれます。 同様に、入れ子になったマスター ページを作成し、それを に Simple.master バインドすると、入れ子になったマスター ページには 2 つのコンテンツ コントロールがあります。

という名前SimpleNested.masterのフォルダーに新しい入れ子になったマスター ページをNestedMasterPages追加してみましょう。 フォルダーを右クリックし、[新しい項目の NestedMasterPages 追加] を選択します。 これにより、図 2 に示す [新しい項目の追加] ダイアログ ボックスが表示されます。 [マスター ページ] テンプレートの種類を選択し、新しいマスター ページの名前を入力します。 新しいマスター ページを入れ子になったマスター ページにする必要があることを示すには、[マスター ページの選択] チェック ボックスをチェックします。

次に、[追加] ボタンをクリックします。 これにより、コンテンツ ページをマスター ページにバインドするときに表示されるのと同じ [マスター ページの選択] ダイアログ ボックスが表示されます (図 3 を参照)。 フォルダー内の Simple.master マスター ページを NestedMasterPages 選択し、[OK] をクリックします。

注意

Web サイト プロジェクト モデルではなく Web アプリケーション プロジェクト モデルを使用して ASP.NET Web サイトを作成した場合、図 2 に示す [新しいアイテムの追加] ダイアログ ボックスに [マスター ページの選択] チェック ボックスは表示されません。 Web アプリケーション プロジェクト モデルを使用するときに入れ子になったマスター ページを作成するには、(マスター ページ テンプレートではなく) 入れ子になったマスター ページ テンプレートを選択する必要があります。 [入れ子になったマスター ページ] テンプレートを選択し、[追加] をクリックすると、図 3 に示すのと同じ [マスター ページの選択] ダイアログ ボックスが表示されます。

[マスター ページの選択] チェック ボックスをオンにして、入れ子になったマスター ページを追加します

図 02: [マスター ページの選択] チェック ボックスをオンにして、入れ子になったマスター ページを追加します (フルサイズの画像を表示する をクリックします)

入れ子になったマスター ページを Simple.master マスター ページにバインドする

図 03: 入れ子になったマスター ページを Simple.master マスター ページにバインドする (フルサイズの画像を表示する をクリックします)

次に示すように、入れ子になったマスター ページの宣言型マークアップには、最上位マスター ページの 2 つの ContentPlaceHolder コントロールを参照する 2 つの Content コントロールが含まれています。

<%@ Master Language="C#" MasterPageFile="~/NestedMasterPages/Simple.master" AutoEventWireup="false" CodeFile="SimpleNested.master.cs" Inherits="NestedMasterPages_SimpleNested" %> 
 <asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server"> 
 </asp:Content> 
 <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server"> 
 </asp:Content>

ディレクティブを <%@ Master %> 除き、入れ子になったマスター ページの最初の宣言型マークアップは、コンテンツ ページを同じ最上位マスター ページにバインドするときに最初に生成されたマークアップと同じです。 コンテンツ ページの <%@ Page %> ディレクティブと同様に <%@ Master %> 、このディレクティブには、入れ子になったマスター ページの親マスター ページを指定する属性が含まれています MasterPageFile 。 入れ子になったマスター ページと同じ最上位マスター ページにバインドされたコンテンツ ページのメイン違いは、入れ子になったマスター ページに ContentPlaceHolder コントロールを含めることができる点です。 入れ子になったマスター ページの ContentPlaceHolder コントロールは、コンテンツ ページがマークアップをカスタマイズできる領域を定義します。

ContentPlaceHolder コントロールに対応する Content コントロールに "Hello, from SimpleNested!" というテキストが表示されるように、この入れ子になったマスター ページを MainContent 更新します。

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server"> 
 <p>Hello, from SimpleNested!</p>
</asp:Content>

この追加を行った後、入れ子になったマスター ページを保存し、 という名前Default.aspxNestedMasterPagesフォルダーに新しいコンテンツ ページを追加し、それをマスター ページにSimpleNested.masterバインドします。 このページを追加すると、コンテンツ コントロールが含まれないことに驚くことがあります (図 4 を参照)。 コンテンツ ページは、 マスター ページの ContentPlaceHolders にのみアクセスできます。 SimpleNested.master には ContentPlaceHolder コントロールが含まれていません。したがって、このマスター ページにバインドされているコンテンツ ページには、コンテンツ コントロールを含めることはできません。

[新しいコンテンツ] ページにコンテンツ コントロールが含まれない

図 04: [新しいコンテンツ] ページにコンテンツ コントロールが含まれない (クリックするとフルサイズの画像が表示されます)

実行する必要がある操作は、入れ子になったマスター ページ (SimpleNested.master) を更新して ContentPlaceHolder コントロールを含めます。 通常、入れ子になったマスター ページには、親マスター ページで定義された各 ContentPlaceHolder に ContentPlaceHolder を含め、その子マスター ページまたはコンテンツ ページが最上位マスター ページの ContentPlaceHolder コントロールを操作できるようにします。

マスター ページを SimpleNested.master 更新して、ContentPlaceHolder を 2 つのコンテンツ コントロールに含めます。 ContentPlaceHolder コントロールに ContentPlaceHolder コントロールが参照する名前と同じ名前を付けます。 つまり、 の ContentPlaceHolder を参照する Content コントロールに、 という名前MainContentの ContentPlaceHolder Simple.masterコントロールSimpleNested.masterMainContent追加します。 ContentPlaceHolder を参照 head する Content コントロールで同じことを行います。

注意

入れ子になったマスター ページの ContentPlaceHolder コントロールに最上位マスター ページの ContentPlaceHolders と同じ名前を付けるのをお勧めしますが、この名前付けの対称性は必要ありません。 入れ子になったマスター ページで ContentPlaceHolder コントロールに任意の名前を付けることができます。 しかし、最上位のマスター ページと入れ子になったマスター ページで同じ名前が使用されている場合、ContentPlaceHolders がページの領域に対応するものを覚える方が簡単です。

これらの追加を行った後、 SimpleNested.master マスター ページの宣言型マークアップは次のようになります。

<%@ Master Language="C#" MasterPageFile="~/NestedMasterPages/Simple.master"AutoEventWireup="false" CodeFile="SimpleNested.master.cs" Inherits="NestedMasterPages_SimpleNested" %> 
 <asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server"> 
 <asp:ContentPlaceHolder ID="head" runat="server"> 
 </asp:ContentPlaceHolder>
 </asp:Content> 
 <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server"> 
 <p>Hello, from SimpleNested!</p>
 <asp:ContentPlaceHolder ID="MainContent" runat="server"> 
 </asp:ContentPlaceHolder>
 </asp:Content>

先ほど作成したコンテンツ ページを Default.aspx 削除してから再追加し、マスター ページに SimpleNested.master バインドします。 今回は、Visual Studio によって に 2 つのコンテンツ コントロールが Default.aspx追加され、 で SimpleNested.master 定義されている ContentPlaceHolders が参照されます (図 6 を参照)。 を参照 MainContentする Content コントロールに、"Hello, from Default.aspx!" というテキストを追加します。

図 5 は、ここに関係する 3 つのエンティティ ( Simple.master、、 SimpleNested.masterおよび) と Default.aspx 、それらが相互にどのように関連しているかを示しています。 図に示すように、入れ子になったマスター ページは、親の ContentPlaceHolder の Content コントロールを実装します。 これらの領域にコンテンツ ページからアクセスできる必要がある場合は、入れ子になったマスター ページで独自の ContentPlaceHolders を Content コントロールに追加する必要があります。

コンテンツ ページのレイアウトを決定する Top-Level と入れ子になったマスター ページ

図 05: コンテンツ ページのレイアウトを決定する Top-Level と入れ子になったマスター ページ (フルサイズの画像を表示する をクリックします)

この動作は、コンテンツ ページまたはマスター ページが親マスター ページでのみ認識される方法を示しています。 この動作は、Visual Studio Designerでも示されます。 図 6 は、 のDesignerをDefault.aspx示しています。 Designerでは、コンテンツ ページから編集可能な領域と、編集できない部分が明確に示されますが、入れ子になったマスター ページの編集可能でない領域と最上位マスター ページの領域は明確に区別されません。

コンテンツ ページに、入れ子になったマスター ページの ContentPlaceHolders のコンテンツ コントロールが含まれるようになりました

図 06: コンテンツ ページに、入れ子になったマスター ページの ContentPlaceHolders のコンテンツ コントロールが含まれるようになりました (フルサイズの画像を表示するをクリックします)

手順 3: 2 つ目の単純な入れ子になったマスター ページを追加する

入れ子になったマスター ページの利点は、入れ子になったマスター ページが複数ある場合により明らかです。 この利点を説明するには、フォルダーに別の入れ子になったマスター ページを NestedMasterPages 作成します。この新しい入れ子になったマスター ページ SimpleNestedAlternate.master に名前を付けて、マスター ページに Simple.master バインドします。 手順 2 で行ったように、入れ子になったマスター ページの 2 つの Content コントロールに ContentPlaceHolder コントロールを追加します。 また、最上位マスター ページ MainContent の ContentPlaceHolder に対応するコンテンツ コントロールに、"Hello, from SimpleNestedAlternate!" というテキストを追加します。 これらの変更を行った後、新しい入れ子になったマスター ページの宣言型マークアップは次のようになります。

<%@ Master Language="C#" MasterPageFile="~/NestedMasterPages/Simple.master" AutoEventWireup="false" CodeFile="SimpleNestedAlternate.master.cs" Inherits="NestedMasterPages_SimpleNestedAlternate" %> 
 <asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
 <asp:ContentPlaceHolder ID="head" runat="server">
 </asp:ContentPlaceHolder> 
 </asp:Content> 
 <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server">
 <p>Hello, from SimpleNestedAlternate!</p> 
 <asp:ContentPlaceHolder ID="MainContent" runat="server">
 </asp:ContentPlaceHolder> 
 </asp:Content>

フォルダーに という名前 Alternate.aspx のコンテンツ ページを NestedMasterPages 作成し、入れ子になったマスター ページに SimpleNestedAlternate.master バインドします。 に対応するコンテンツ コントロールに、"Hello, from Alternate!" というテキストを MainContent追加します。 図 7 は、Visual Studio Designerで表示される場合を示していますAlternate.aspx

Alternate.aspxは SimpleNestedAlternate.master マスター ページにバインドされています

図 07: Alternate.aspx マスター ページに SimpleNestedAlternate.master バインドされています (フルサイズの画像を表示する場合はクリックします)

図 7 のDesignerと図 6 のDesignerを比較します。 どちらのコンテンツ ページも、最上位マスター ページ () で定義されている同じレイアウトをSimple.master共有します。つまり、"入れ子になったマスター ページチュートリアル (Simple)" タイトルです。 ただし、どちらも親マスター ページに個別のコンテンツが定義されています。図 6 のテキスト "Hello, from SimpleNested!" と図 7 の "Hello, from SimpleNestedAlternate!" です。 確かに、ここでのこれらの違いは簡単ですが、この例を拡張して、より意味のある違いを含めることができます。 たとえば、ページには SimpleNested.master コンテンツ ページに固有のオプションを含むメニューが含まれている場合と、 SimpleNestedAlternate.master それにバインドするコンテンツ ページに関連する情報が含まれている場合があります。

ここで、包括的なサイト レイアウトを変更する必要があるとします。 たとえば、すべてのコンテンツ ページに共通のリンクの一覧を追加するとします。 これを実現するために、 Simple.master最上位のマスター ページ である を更新します。 そこに加えられた変更は、入れ子になったマスター ページと、拡張機能によってコンテンツ ページに直ちに反映されます。

包括的なサイト レイアウトを簡単に変更できるようにするには、マスター ページをSimple.master開き、 要素と mainContent<div> 要素の間に次のマークアップをtopContent追加します。

<div id="navContent"> 
 <asp:HyperLink ID="lnkDefault" runat="server" 
 NavigateUrl="~/NestedMasterPages/Default.aspx" 
 Text="Nested Master Page Example 1" /> 
 | 
 <asp:HyperLink ID="lnkAlternate" runat="server" 
 NavigateUrl="~/NestedMasterPages/Alternate.aspx" 
 Text="Nested Master Page Example 2" /> 
</div>

これにより、または SimpleNestedAlternate.masterにバインドされるすべてのページの上部に Simple.masterSimpleNested.master2 つのリンクが追加されます。これらの変更は、入れ子になったすべてのマスター ページとそのコンテンツ ページに直ちに適用されます。 図 8 は、ブラウザーを使用して表示する場合を示しています Alternate.aspx 。 ページの上部にリンクが追加されていることに注意してください (図 7 と比較)。

Top-Level マスター ページに変更すると、入れ子になったマスター ページとそのコンテンツ ページにすぐに反映されます

図 08: Top-Level マスター ページに変更され、入れ子になったマスター ページとそのコンテンツ ページにすぐに反映されます (フルサイズの画像を表示する をクリックします)

管理セクションに入れ子になったマスター ページを使用する

この時点で、入れ子になったマスター ページの利点を確認し、ASP.NET アプリケーションでそれらを作成して使用する方法を確認しました。 ただし、手順 1、2、3 の例では、新しい最上位マスター ページ、新しい入れ子になったマスター ページ、および新しいコンテンツ ページの作成が含まれています。 既存の最上位マスター ページとコンテンツ ページを含む Web サイトに新しい入れ子になったマスター ページを追加する場合はどうでしょうか。

入れ子になったマスター ページを既存の Web サイトに統合し、既存のコンテンツ ページに関連付けるには、最初から始めるよりも少し手間がかかります。 手順 4、5、6、7 では、管理者の指示を含み、フォルダー内の ASP.NET ページで使用される という名前 AdminNested.master の新しい入れ子になったマスター ページを含むようにデモ アプリケーションを拡張する際に、これらの課題について ~/Admin 説明します。

入れ子になったマスター ページをデモ アプリケーションに統合すると、次のハードルが生まれます。

  • フォルダー内の既存の ~/Admin コンテンツ ページには、マスター ページからの特定の期待があります。 まず、特定の ContentPlaceHolder コントロールが存在することを想定しています。 さらに、 ページと ページは~/Admin/AddProduct.aspx、マスター ページのパブリック RefreshRecentProductsGrid メソッドを呼び出すか、そのプロパティをGridMessageText設定するか、イベントのPricesDoubledイベント ハンドラーを持~/Admin/Products.aspxちます。 そのため、入れ子になったマスター ページは、同じ ContentPlaceHolders とパブリック メンバーを提供する必要があります。
  • 前のチュートリアルでは、 クラスを拡張して、BasePageSession 変数に基づいてオブジェクトの MasterPageFile プロパティを動的に設定Pageしました。 入れ子になったマスター ページを使用する場合、動的マスター ページをサポートするにはどうすればよいですか?

この 2 つの課題は、入れ子になったマスター ページを構築し、既存のコンテンツ ページから使用する場合に発生します。 これらの問題が発生したら、調査してマウントします。

手順 4: 入れ子になったマスター ページを作成する

最初のタスクは、[管理] セクションのページで使用する入れ子になったマスター ページを作成することです。 手順 2 で説明したように、新しい入れ子になったマスター ページを追加するときは、入れ子になったマスター ページの親マスター ページを指定する必要があります。 ただし、最上位レベルのマスター ページと という 2 つのマスター ページがあります Site.masterAlternate.master。 前のチュートリアルで作成Alternate.masterし、実行時に Page オブジェクトの プロパティを BasePage Session 変数のMasterPageFile値にSite.masterAlternate.master応じて または に設定するコードを MyMasterPage クラスに記述したことを思い出してください。

適切な最上位マスター ページを使用するように、入れ子になったマスター ページを構成するにはどうすればよいですか? 2 つのオプションがあります。

  • 入れ子になったマスター ページと AdminNestedAlternate.masterを 2 つ作成し、AdminNestedSite.masterそれぞれ最上位のマスター ページSite.masterAlternate.masterにバインドします。 でBasePage、オブジェクトMasterPageFileの をPage適切な入れ子になったマスター ページに設定します。
  • 入れ子になったマスター ページを 1 つ作成し、コンテンツ ページでこの特定のマスター ページを使用します。 次に、実行時に、入れ子になったマスター ページの MasterPageFile プロパティを実行時に適切な最上位マスター ページに設定する必要があります。 (ここまででわかるように、マスター ページにも プロパティがあります MasterPageFile

2 番目のオプションを使用してみましょう。 という名前AdminNested.masterのフォルダーに、入れ子になったマスター ページ ファイルを ~/Admin 1 つ作成します。 と Alternate.master の両方Site.masterに ContentPlaceHolder コントロールのセットが同じであるため、バインド先のマスター ページは関係ありませんが、一貫性のためにバインドSite.masterすることをお勧めします。

~/管理 フォルダーに入れ子になったマスター ページを追加します。

図 09: 入れ子になったマスター ページをフォルダーに ~/Admin 追加する。 (クリックするとフルサイズの画像が表示されます)

入れ子になったマスター ページは 4 つの ContentPlaceHolder コントロールを持つマスター ページにバインドされるため、Visual Studio は、新しい入れ子になったマスター ページ ファイルの初期マークアップに 4 つのコンテンツ コントロールを追加します。 手順 2 と 3 で行ったように、各コンテンツ コントロールに ContentPlaceHolder コントロールを追加し、最上位マスター ページの ContentPlaceHolder コントロールと同じ名前を付けます。 また、ContentPlaceHolder に対応する Content コントロールに次のマークアップを MainContent 追加します。

<div class="instructions"> 
 <b>Administration Instructions:</b>
 <br /> 
 The pages in the Administration section allow you, the Administrator, to 
 add new products and view existing products. 
</div>

次にinstructions、 および AlternateStyles.css CSS ファイルで CSS クラスをStyles.css定義します。 次の CSS ルールにより、 クラスで instructions スタイル設定された HTML 要素は、薄い黄色の背景色と黒の単色の境界線で表示されます。

.instructions 
{ 
 padding: 6px; 
 border: dashed 1px black; 
 background-color: #ffb; 
 margin-bottom: 10px; 
}

このマークアップは入れ子になったマスター ページに追加されているため、この入れ子になったマスター ページ (つまり、[管理] セクションのページ) を使用するページにのみ表示されます。

入れ子になったマスター ページにこれらの追加を行った後、宣言型マークアップは次のようになります。

<%@ Master Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="false" CodeFile="AdminNested.master.cs" Inherits="Admin_AdminNested" %> 
 <asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server"> 
 <asp:ContentPlaceHolder ID="head" runat="server"> 
 </asp:ContentPlaceHolder>
 </asp:Content> 
 <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server"> 
 <div class="instructions">
 <b>Administration Instructions:</b>
 <br /> 
 The pages in the Administration section allow you, the Administrator, to 
 add new products and view existing products. 
 </div> 
 <asp:ContentPlaceHolder ID="MainContent" runat="server"> 
 </asp:ContentPlaceHolder>
 </asp:Content> 
 <asp:Content ID="Content3" ContentPlaceHolderID="QuickLoginUI" Runat="Server"> 
 <asp:ContentPlaceHolder ID="QuickLoginUI" runat="server"> 
 </asp:ContentPlaceHolder>
 </asp:Content> 
 <asp:Content ID="Content4" ContentPlaceHolderID="LeftColumnContent" Runat="Server"> 
 <asp:ContentPlaceHolder ID="LeftColumnContent" runat="server"> 
 </asp:ContentPlaceHolder>
 </asp:Content>

各 Content コントロールには ContentPlaceHolder コントロールがあり、ContentPlaceHolder コントロールの ID プロパティには、最上位マスター ページの対応する ContentPlaceHolder コントロールと同じ値が割り当てられていることに注意してください。 さらに、管理セクション固有のマークアップが ContentPlaceHolder に MainContent 表示されます。

図 10 は、Visual Studio のAdminNested.masterDesignerで表示される入れ子になったマスター ページを示しています。 コンテンツ コントロールの上部にある黄色のボックスに手順が MainContent 表示されます。

入れ子になったマスター ページでは、Top-Level マスター ページが管理者の指示を含むように拡張されます。

図 10: 入れ子になったマスター ページは、Top-Level マスター ページを拡張して、管理者の指示を含めます。 (クリックするとフルサイズの画像が表示されます)

手順 5: 新しい入れ子になったマスター ページを使用するように既存のコンテンツ ページを更新する

新しいコンテンツ ページを [管理] セクションに追加するたびに、先ほど作成した AdminNested.master マスター ページにバインドする必要があります。 しかし、既存のコンテンツ ページはどうでしょうか。 現在、サイト内のすべてのコンテンツ ページは クラスから BasePage 派生しており、実行時にプログラムによってコンテンツ ページのマスター ページが設定されます。 これは、[管理] セクションのコンテンツ ページに必要な動作ではありません。 代わりに、これらのコンテンツ ページで常にページを使用する AdminNested.master 必要があります。 入れ子になったマスター ページは、実行時に右の最上位レベルのコンテンツ ページを選択する必要があります。

この目的の動作を実現する最善の方法は、 クラスを拡張する という名前 AdminBasePage の新しいカスタム 基本ページ クラスを BasePage 作成することです。 AdminBasePageをオーバーライドSetMasterPageFileし、オブジェクトの MasterPageFilePageハードコーディングされた値 "~/管理/AdminNested.master" に設定できます。 このようにして、 からAdminBasePage派生したページは を使用AdminNested.masterしますが、 からBasePage派生するすべてのページでは、Session 変数のMyMasterPage値に基づいてプロパティが "~/Site.master" または "~/Alternate.master" に動的に設定されますMasterPageFile

まず、 という名前AdminBasePage.csのフォルダーに新しいクラス ファイルをApp_Code追加します。 AdminBasePage拡張BasePageしてから、 メソッドをオーバーライドしますSetMasterPageFile。 このメソッドでは、MasterPageFile値 "~/管理/AdminNested.master" を割り当てます。 これらの変更を行った後、クラス ファイルは次のようになります。

public class AdminBasePage : BasePage 
{ 
    protected override void SetMasterPageFile() 
    { 
        this.MasterPageFile = "~/Admin/AdminNested.master"; 
    } 
}

次に、[管理] セクションの既存のコンテンツ ページを ではなく からAdminBasePageBasePage派生させる必要があります。 フォルダー内の各コンテンツ ページの分離コード クラス ファイルに移動し、この変更を ~/Admin 行います。 たとえば、 では ~/Admin/Default.aspx 、分離コード クラスの宣言を次から変更します。

public partial class Admin_Default : BasePage

移動先:

public partial class Admin_Default : AdminBasePage

図 11 は、最上位のマスター ページ (Site.master または Alternate.master)、入れ子になったマスター ページ (AdminNested.master)、および [管理] セクションのコンテンツ ページが相互にどのように関連しているかを示しています。

入れ子になったマスター ページ管理セクションのページに固有のコンテンツを定義します

図 11: 入れ子になったマスター ページは、[管理] セクションのページに固有のコンテンツを定義します (フルサイズの画像を表示する をクリックします)

手順 6: マスター ページのパブリック メソッドとプロパティをミラーリングする

ページと ページは~/Admin/AddProduct.aspx、プログラムによってマスター ページ~/Admin/AddProduct.aspxと対話することを思い出してください。マスター ページのパブリック RefreshRecentProductsGrid メソッドを呼び出し、そのプロパティをGridMessageText設定します~/Admin/Products.aspx。イベントのPricesDoubledイベント ハンドラー~/Admin/Products.aspxがあります。 前のチュートリアルでは、これらのパブリック メンバーを定義する抽象 BaseMasterPage クラスを作成しました。

ページと ~/Admin/Products.aspx ページは~/Admin/AddProduct.aspx、マスター ページが クラスからBaseMasterPage派生していることを前提としています。 ただし、現在、ページは AdminNested.master クラスを System.Web.UI.MasterPage 拡張しています。 その結果、 にアクセス~/Admin/Products.aspxInvalidCastExceptionすると、"型 'ASP.admin_adminnested_master' のオブジェクトを 'BaseMasterPage' 型にキャストできません" というメッセージがスローされます。

これを修正するには、分離コード クラスで を AdminNested.master 拡張 BaseMasterPageする必要があります。 入れ子になったマスター ページの分離コード クラス宣言を次から更新します。

public partial class Admin_AdminNested : System.Web.UI.MasterPage

移動先:

public partial class Admin_AdminNested : BaseMasterPage

まだ完了していません。 BaseMasterPageクラスは抽象であるため、メンバーRefreshRecentProductsGridGridMessageTextをオーバーライドするabstract必要があります。 これらのメンバーは、最上位のマスター ページでユーザー インターフェイスを更新するために使用されます。 (実際には、マスター ページのみがこれらのメソッドを Site.master 使用しますが、両方の最上位マスター ページではこれらのメソッドが実装されます。両方とも を拡張 BaseMasterPageするためです)。

ではこれらのメンバー AdminNested.masterを実装する必要があります。これらの実装はすべて、入れ子になったマスター ページで使用される最上位マスター ページで同じメンバーを呼び出すだけです。 たとえば、[管理] セクションのコンテンツ ページが入れ子になったマスター ページの RefreshRecentProductsGrid メソッドを呼び出すときに、入れ子になったマスター ページで行う必要があるのは、その後、 Site.master メソッドまたは Alternate.masterRefreshRecentProductsGrid メソッドです。

これを実現するには、まず、 の先頭に次 @MasterTypeAdminNested.masterディレクティブを追加します。

<%@ MasterType TypeName="BaseMasterPage" %>

ディレクティブは、 @MasterType という名前の分離コード クラスに厳密に型指定されたプロパティを追加することを思い出 Masterしてください。 次に、 メンバーと GridMessageText メンバーをRefreshRecentProductsGridオーバーライドし、単に の対応するメソッドへの呼び出しをMaster委任します。

public partial class Admin_AdminNested : BaseMasterPage 
{ 
    public override void RefreshRecentProductsGrid() 
    { 
        Master.RefreshRecentProductsGrid();
    } 
    public override string GridMessageText
    { 
        get 
        {
            return Master.GridMessageText;
        } 
        set
        { 
            Master.GridMessageText = value; 
        } 
    }
}

このコードを配置すると、[管理] セクションのコンテンツ ページにアクセスして使用できるようになります。 図 12 は、ブラウザーで ~/Admin/Products.aspx 表示したときのページを示しています。 ご覧のように、ページには、入れ子になったマスター ページで定義されている [管理手順] ボックスが含まれています。

[管理] セクションのコンテンツ ページには、各ページの上部にある手順が含まれます

図 12: [管理] セクションの [コンテンツ ページ] には、各ページの上部にある手順が含まれます (フルサイズの画像を表示するにはクリックします)

手順 7: 実行時に適切な Top-Level マスター ページを使用する

[管理] セクションのすべてのコンテンツ ページは完全に機能しますが、すべて同じ最上位マスター ページを使用し、 で ChooseMasterPage.aspxユーザーによって選択されたマスター ページは無視されます。 この動作は、入れ子になったマスター ページの プロパティが MasterPageFile ディレクティブで <%@ Master %> 静的に にSite.master設定されているためです。

エンド ユーザーが選択した最上位のマスター ページを使用するには、 の プロパティを AdminNested.masterSession 変数の MasterPageFile 値に設定する MyMasterPage 必要があります。 でコンテンツ ページのMasterPageFileプロパティBasePageを設定するため、入れ子になったマスター ページの MasterPageFile プロパティを の分離コード クラスまたは の分離コード クラスにBaseMasterPageAdminNested.master設定すると考えられます。 ただし、PreInit ステージの終わりまでに プロパティを MasterPageFile 設定する必要があるため、これは機能しません。 プログラムでマスター ページからページ ライフサイクルをタップできる最も早い時間は、Init ステージ (PreInit ステージの後に発生します) です。

そのため、コンテンツ ページから入れ子になったマスター ページの MasterPageFile プロパティを設定する必要があります。 マスター ページを使用する唯一のコンテンツ ページは AdminNested.master 、 から AdminBasePage派生します。 したがって、このロジックをそこに配置できます。 手順 5 では、 メソッドをSetMasterPageFileオーバーロードし、オブジェクトの MasterPageFile プロパティを Page "~/管理/AdminNested.master" に設定します。 を更新 SetMasterPageFile して、マスター ページの MasterPageFile プロパティを Session に格納された結果に設定します。

public class AdminBasePage : BasePage 
{ 
    protected override void SetMasterPageFile() 
    { 
        this.MasterPageFile = "~/Admin/AdminNested.master"; 
        Page.Master.MasterPageFile = base.GetMasterPageFileFromSession(); 
    } 
}

前のチュートリアルで クラスにBasePage追加した メソッドはGetMasterPageFileFromSession、Session 変数の値に基づいて適切なマスター ページ ファイル パスを返します。

この変更により、ユーザーのマスター ページの選択が [管理] セクションに引き継がれる。 図 13 は図 12 と同じページを示していますが、ユーザーがマスター ページの選択を に Alternate.master変更した後。

[入れ子になった管理] ページでは、ユーザーによって選択された Top-Level マスター ページが使用されます

図 13: 入れ子になった管理ページでは、ユーザーによって選択された Top-Level マスター ページを使用します (フルサイズの画像を表示する をクリックします)

まとめ

コンテンツ ページをマスター ページにバインドする方法と同様に、子マスター ページを親マスター ページにバインドすることで、入れ子になったマスター ページを作成できます。 子マスター ページでは、親の ContentPlaceHolders ごとに Content コントロールを定義できます。その後、独自の ContentPlaceHolder コントロール (およびその他のマークアップ) をこれらの Content コントロールに追加できます。 入れ子になったマスター ページは、すべてのページが包括的な外観を共有する大規模な Web アプリケーションで非常に便利ですが、サイトの特定のセクションでは一意のカスタマイズが必要です。

プログラミングに満足!

もっと読む

このチュートリアルで説明するトピックの詳細については、次のリソースを参照してください。

著者について

複数の ASP/ASP.NET 書籍の著者であり、4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジと協力しています。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズ・ティーチ・自分自身 ASP.NET 24時間で3.5です。 Scott は、 または mitchell@4GuysFromRolla.com のブログから http://ScottOnWriting.NETアクセスできます。

特別な感謝

このチュートリアル シリーズは、多くの役に立つ校閲者によってレビューされました。 今後の MSDN の記事を確認することに関心がありますか? もしそうなら、私に行を落としてください mitchell@4GuysFromRolla.com