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

作成者: Scott Mitchell

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

はじめに

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

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

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

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

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

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

注意

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

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

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

注意

ここでは、サイトにマスター ページ Site.masterが 1 つだけあるとします。 このチュートリアルの後半の「管理セクションに入れ子になったマスター ページを使用する」から始まる 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>

このマークアップでは、ページの上部に "Nested Master Pages (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="VB" MasterPageFile="~/NestedMasterPages/Simple.master" AutoEventWireup="false" CodeFile="SimpleNested.master.vb" 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="VB" MasterPageFile="~/NestedMasterPages/Simple.master" AutoEventWireup="false" CodeFile="SimpleNested.master.vb" 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="VB" MasterPageFile="~/NestedMasterPages/Simple.master" AutoEventWireup="false" CodeFile="SimpleNestedAlternate.master.vb" 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し、実行時にオブジェクトの プロパティを BasePage Session 変数のMasterPageFile値にSite.masterAlternate.master応じて または に設定Pageするコードを 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="VB" MasterPageFile="~/Site.master" AutoEventWireup="false" CodeFile="AdminNested.master.vb" 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オーバーライドし、オブジェクトの MasterPageFile をハードコーディングされた値 "~/管理/AdminNested.master" に設定Pageできます。 このようにして、 から AdminBasePage 派生したページは を使用 AdminNested.masterしますが、 から BasePage 派生するすべてのページでは MasterPageFile 、Session 変数の MyMasterPage 値に基づいてプロパティが "~/Site.master" または "~/Alternate.master" に動的に設定されます。

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

Public Class AdminBasePage 
 Inherits BasePage 
 Protected Overrides Sub SetMasterPageFile() 
 Me.MasterPageFile = "~/Admin/AdminNested.master" 
 End Sub 
End Class

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

Partial Class Admin_Default 
 Inherits BasePage

移動先:

Partial Class Admin_Default 
 Inherits 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があります。 前のチュートリアルでは、これらのパブリック メンバーを MustInheritBaseMasterPage 定義するクラスを作成しました。

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

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

Partial Class Admin_AdminNested 
 Inherits System.Web.UI.MasterPage

移動先:

Partial Class Admin_AdminNested 
 Inherits BaseMasterPage

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

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

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

<%@ MasterType TypeName="BaseMasterPage" %>

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

Partial Class Admin_AdminNested 
 Inherits BaseMasterPage 
 Public Overrides Property GridMessageText() As String 
 Get 
 Return Master.GridMessageText 
 End Get 
 Set(ByVal value As String) 
 Master.GridMessageText = value 
 End Set 
 End Property 
 Public Overrides Sub RefreshRecentProductsGrid()
 Master.RefreshRecentProductsGrid()
 End Sub 
End Class

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

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

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

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

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

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

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

Public Class AdminBasePage 
 Inherits BasePage 
 Protected Overrides Sub SetMasterPageFile() 
 Me.MasterPageFile = "~/Admin/AdminNested.master" 
 Page.Master.MasterPageFile = MyBase.GetMasterPageFileFromSession() 
 End Sub 
End Class

前のチュートリアルで クラスに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