次の方法で共有


プログラムでマスター ページを指定する (C#)

作成者: Scott Mitchell

PreInit イベント ハンドラーを使用してプログラムでコンテンツ ページのマスター ページを設定する方法について説明します。

はじめに

マスター ページを使用した Site-Wide レイアウトの作成」の第 1 の例以降、すべてのコンテンツ ページは ディレクティブの 属性を MasterPageFile 使用して宣言的にマスター ページを @Page 参照しています。 たとえば、次 @Page のディレクティブは、コンテンツ ページをマスター ページ Site.masterにリンクします。

<%@ Page Language="C#" MasterPageFile="~/Site.master" ... %>

Page名前空間の System.Web.UI クラスには、コンテンツ ページのマスター ページへのパスを返すプロパティが含まれていますMasterPageFile。これは、 ディレクティブによって@Page設定されるこのプロパティです。 このプロパティを使用して、コンテンツ ページのマスター ページをプログラムで指定することもできます。 この方法は、ページにアクセスするユーザーなどの外部要因に基づいてマスター ページを動的に割り当てる場合に便利です。

このチュートリアルでは、Web サイトに 2 つ目のマスター ページを追加し、実行時に使用するマスター ページを動的に決定します。

手順 1: ページのライフサイクルの概要

コンテンツ ページである ASP.NET ページの要求が Web サーバーに到着するたびに、ASP.NET エンジンはページの Content コントロールをマスター ページの対応する ContentPlaceHolder コントロールに融合する必要があります。 この融合により、一般的なページ ライフサイクルを進めることができる単一のコントロール階層が作成されます。

図 1 は、この融合を示しています。 図 1 の手順 1 は、初期コンテンツとマスター ページ コントロール階層を示しています。 PreInit ステージの末尾に、ページ内のコンテンツ コントロールがマスター ページの対応する ContentPlaceHolders に追加されます (手順 2)。 この融合後、マスター ページは、融合されたコントロール階層のルートとして機能します。 その後、この融合コントロール階層がページに追加され、最終的なコントロール階層が生成されます (手順 3)。 結果として、ページのコントロール階層には、融合されたコントロール階層が含まれます。

マスター ページとコンテンツ ページのコントロール階層は、PreInit ステージ中に結合されます

図 01: PreInit ステージ中にマスター ページとコンテンツ ページのコントロール階層が結合されている (フルサイズの画像を表示する をクリックします)

手順 2: コードからプロパティを設定するMasterPageFile

この融合のマスター ページの部分は、オブジェクトMasterPageFileの プロパティのPage値によって異なります。 ディレクティブで 属性をMasterPageFile@Page設定すると、ページのライフサイクルの最初のMasterPageFileステージである初期化ステージ中に の プロパティを割り当てるPageという実質的な効果があります。 または、プログラムでこのプロパティを設定することもできます。 ただし、図 1 の融合が行われる前に、このプロパティを設定することが不可欠です。

PreInit ステージの開始時に、オブジェクトはそのイベントをPage発生させ、そのPreInitメソッドをOnPreInit呼び出します。 プログラムでマスター ページを設定するには、イベントのイベント ハンドラー PreInit を作成するか、 メソッドを OnPreInit オーバーライドします。 両方のアプローチを見てみましょう。

まず、サイトのホームページの分離コード クラス ファイルを開 Default.aspx.csきます。 次のコードを入力して、ページのイベントの PreInit イベント ハンドラーを追加します。

protected void Page_PreInit(object sender, EventArgs e) 
{ 
}

ここから、 プロパティを MasterPageFile 設定できます。 値 "~/Site.master" を プロパティに割り当てるようにコードを MasterPageFile 更新します。

protected void Page_PreInit(object sender, EventArgs e) 
{
    this.MasterPageFile = "~/Site.master"; 
}

ブレークポイントを設定してデバッグを開始すると、ページにアクセスするたびにDefault.aspx、またはこのページへのポストバックが発生するたびに、イベント ハンドラーが実行されMasterPageFilePage_PreInitプロパティが "~/Site.master" に割り当てられます。

または、クラスの OnPreInit メソッドをPageオーバーライドし、そこで プロパティをMasterPageFile設定することもできます。 この例では、マスター ページを特定のページに設定するのではなく、 から BasePage設定してみましょう。 マスター ページのチュートリアルの「タイトル、メタ タグ、およびその他の HTML ヘッダーの指定」でカスタム基本ページ クラス (BasePage) を作成したことを思い出してください。 現在BasePage、クラスの OnLoadComplete メソッドをPageオーバーライドし、サイト マップ データに基づいてページのTitleプロパティを設定します。 を 更新 BasePage して、 メソッドを OnPreInit オーバーライドして、プログラムによってマスター ページを指定しましょう。

protected override void OnPreInit(EventArgs e) 
{ 
    this.MasterPageFile = "~/Site.master"; 
    base.OnPreInit(e); 
}

すべてのコンテンツ ページは から BasePage派生しているため、すべてのコンテンツ ページにプログラムによってマスター ページが割り当てられるようになりました。 この時点で、 のPreInitDefault.aspx.csイベント ハンドラーは余分です。自由に削除してください。

ディレクティブについて@Page

少しわかりにくいのは、コンテンツ ページのMasterPageFileプロパティが 2 つの場所で指定されていることです。クラスの OnPreInit メソッドでBasePageプログラムを使用する方法と、各コンテンツ ページの @Page ディレクティブの 属性を使用MasterPageFileする方法です。

ページ ライフサイクルの最初のステージは、初期化ステージです。 この段階では、Pageオブジェクトの MasterPageFile プロパティに ディレクティブ内@Pageの 属性のMasterPageFile値が割り当てられます (指定されている場合)。 PreInit ステージは初期化ステージに従い、ここでプログラムでオブジェクトの MasterPageFile プロパティをPage設定し、 ディレクティブから割り当てられた値を@Page上書きします。 オブジェクトの プロパティを Page プログラムで設定しているため、エンド ユーザーの MasterPageFile エクスペリエンスに MasterPageFile 影響を与えることなく、 ディレクティブから @Page 属性を削除できます。 これを理解するには、 内の ディレクティブDefault.aspxから 属性をMasterPageFile@Page削除し、ブラウザーからページにアクセスします。 予想どおり、出力は 属性が削除される前と同じです。

プロパティが ディレクティブを MasterPageFile 使用して @Page 設定されているか、プログラムによって設定されるかは、エンド ユーザーのエクスペリエンスに関係なく行われます。 ただし、 ディレクティブの MasterPageFile@Page 属性は、デザイン時に Visual Studio によって使用され、Designerで WYSIWYG ビューが生成されます。 Visual Studio で にDefault.aspx戻り、Designerに移動すると、"マスター ページ エラー: ページにはマスター ページ参照を必要とするコントロールがありますが、何も指定されていない" というメッセージが表示されます (図 2 を参照)。

つまり、Visual Studio で豊富なデザイン時エクスペリエンスを@Page実現するには、 ディレクティブに 属性を残すMasterPageFile必要があります。

Visual Studio では、<span class=@Page ディレクティブの MasterPageFile 属性を使用してデザイン ビューをレンダリングします" />

図 02: Visual Studio は ディレクティブの MasterPageFile 属性を@Page使用してデザイン ビューをレンダリングします (フルサイズの画像を表示する場合はクリックします)

手順 3: 代替マスター ページを作成する

コンテンツ ページのマスター ページは実行時にプログラムで設定できるため、外部条件に基づいて特定のマスター ページを動的に読み込むことができます。 この機能は、サイトのレイアウトがユーザーによって異なる必要がある状況で役立ちます。 たとえば、ブログ エンジン Web アプリケーションでは、各レイアウトが異なるマスター ページに関連付けられているブログのレイアウトをユーザーが選択できる場合があります。 実行時に、訪問者がユーザーのブログを表示している場合、Web アプリケーションはブログのレイアウトを決定し、対応するマスター ページをコンテンツ ページに動的に関連付ける必要があります。

いくつかの外部条件に基づいて、実行時にマスター ページを動的に読み込む方法を見てみましょう。 現在、この Web サイトにはマスター ページSite.master () が 1 つだけ含まれています。 実行時にマスター ページを選択する方法を示すために、別のマスター ページが必要です。 この手順では、新しいマスター ページの作成と構成に焦点を当てます。 手順 4 では、実行時に使用するマスター ページを決定する方法について説明します。

という名前 Alternate.masterのルート フォルダーに新しいマスター ページを作成します。 また、 という名前 AlternateStyles.cssの Web サイトに新しいスタイル シートを追加します。

別のマスター ページと CSS ファイルを Web サイトに追加する

図 03: Web サイトに別のマスター ページと CSS ファイルを追加する (フルサイズの画像を表示する をクリックします)

マスター ページを Alternate.master デザインして、タイトルがページの上部に表示され、中央に配置され、海軍の背景に表示されるようにしました。 左側の列を調べ、そのコンテンツを ContentPlaceHolder コントロールの下 MainContent に移動しました。これはページの幅全体にまたがっています。 さらに、順序付けられていないレッスンリストを作成し、上 MainContentの水平リストに置き換えました。 また、マスター ページで使用されるフォントと色も更新しました (また、拡張によって、そのコンテンツ ページ)。 図 4 は、マスター ページを使用する場合をAlternate.master示していますDefault.aspx

注意

ASP.NET には 、テーマを定義する機能が含まれています。 Theme は、実行時にページに適用できる画像、CSS ファイル、およびスタイル関連の Web コントロール プロパティ設定のコレクションです。 テーマは、サイトのレイアウトが表示される画像と CSS ルールによってのみ異なる場合に行く方法です。 異なる Web コントロールの使用や、レイアウトが大幅に異なるなど、レイアウトが大幅に異なる場合は、個別のマスター ページを使用する必要があります。 テーマの詳細については、このチュートリアルの最後にある「さらに読む」セクションを参照してください。

コンテンツ ページで新しい外観を使用できるようになりました

図 04: コンテンツ ページで新しい外観を使用できるようになりました (クリックするとフルサイズの画像が表示されます)

マスター ページとコンテンツ ページのマークアップが融合されると、 MasterPage クラスは、コンテンツ ページ内のすべてのコンテンツ コントロールがマスター ページの ContentPlaceHolder を参照していることを確認します。 存在しない ContentPlaceHolder を参照する Content コントロールが見つかった場合、例外がスローされます。 言い換えると、コンテンツ ページに割り当てられているマスター ページには、コンテンツ ページ内のコンテンツ コントロールごとに ContentPlaceHolder が必要です。

Site.masterマスター ページには、次の 4 つの ContentPlaceHolder コントロールが含まれています。

  • head
  • MainContent
  • QuickLoginUI
  • LeftColumnContent

当社のウェブサイトのコンテンツページの一部には、1つまたは2つのコンテンツコントロールが含まれています。他のユーザーには、使用可能な各 ContentPlaceHolders の Content コントロールが含まれます。 すべての ContentPlaceHolders Site.master のコンテンツ コントロールを持つコンテンツ ページに新しいマスター ページ (Alternate.master) を割り当てることができる場合は、 と同じ ContentPlaceHolder コントロールSite.masterも含める必要がありますAlternate.master

マスター ページを Alternate.master 自分のページに似た外観にするには (図 4 を参照)、まずスタイル シートでマスター ページのスタイルを AlternateStyles.css 定義します。 に次の規則を AlternateStyles.css追加します。

body 
{ 
 font-family: Comic Sans MS, Arial; 
 font-size: medium; 
 margin: 0px; 
} 
#topContent 
{ 
 text-align: center; 
 background-color: Navy; 
 color: White; 
 font-size: x-large;
 text-decoration: none; 
 font-weight: bold; 
 padding: 10px; 
 height: 50px;
} 
#topContent a 
{ 
 text-decoration: none; 
 color: White; 
} 
#navContent 
{ 
 font-size: small; 
 text-align: center; 
} 
#footerContent 
{ 
 padding: 10px; 
 font-size: 90%; 
 text-align: center; 
 border-top: solid 1px black; 
} 
#mainContent 
{ 
 text-align: left; 
 padding: 10px; 
}

次に、次の宣言型マークアップを に追加します Alternate.master。 ご覧のように、 には、 Alternate.master の ContentPlaceHolder コントロールと同じ ID 値を持つ 4 つの ContentPlaceHolder コントロールが Site.master含まれています。 さらに、ASP.NET AJAX フレームワークを使用する Web サイトのページに必要な ScriptManager コントロールも含まれています。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head id="Head1" runat="server"> 
 <title>Untitled Page</title>
 <asp:ContentPlaceHolder id="head" runat="server">
 </asp:ContentPlaceHolder> 
 <link href="AlternateStyles.css" rel="stylesheet" type="text/css" /> 
</head> 
<body> 
 <form id="form1" runat="server"> 
 <asp:ScriptManager ID="MyManager" runat="server"> 
 </asp:ScriptManager>
 <div id="topContent">
 <asp:HyperLink ID="lnkHome" runat="server" NavigateUrl="~/Default.aspx" 
 Text="Master Pages Tutorials" /> 
 </div>
 <div id="navContent">
 <asp:ListView ID="LessonsList" runat="server" 
 DataSourceID="LessonsDataSource">
 <LayoutTemplate>
 <asp:PlaceHolder runat="server" ID="itemPlaceholder" /> 
 </LayoutTemplate>
 <ItemTemplate>
 <asp:HyperLink runat="server" ID="lnkLesson" 
 NavigateUrl='<%# Eval("Url") %>' 
 Text='<%# Eval("Title") %>' /> 
 </ItemTemplate>
 <ItemSeparatorTemplate> | </ItemSeparatorTemplate> 
 </asp:ListView>
 <asp:SiteMapDataSource ID="LessonsDataSource" runat="server" 
 ShowStartingNode="false" /> 
 </div>
 <div id="mainContent">
 <asp:ContentPlaceHolder id="MainContent" runat="server"> 
 </asp:ContentPlaceHolder>
 </div> 
 <div id="footerContent">
 <p> 
 <asp:Label ID="DateDisplay" runat="server"></asp:Label> 
 </p>
 <asp:ContentPlaceHolder ID="QuickLoginUI" runat="server"> 
 </asp:ContentPlaceHolder>
 <asp:ContentPlaceHolder ID="LeftColumnContent" runat="server"> 
 </asp:ContentPlaceHolder>
 </div> 
 </form>
</body> 
</html>

新しいマスター ページのテスト

この新しいマスター ページをBasePageテストするには、プロパティに値 "~/Alternate.master" が割り当てるようにMasterPageFileクラスのOnPreInitメソッドを更新し、Web サイトにアクセスします。 と の 2 つ ~/Admin/AddProduct.aspx~/Admin/Products.aspxを除き、すべてのページがエラーなしで機能する必要があります。 で DetailsView ~/Admin/AddProduct.aspx に製品を追加すると NullReferenceException 、マスター ページ GridMessageText の プロパティの設定を試みるコード行から が作成されます。 にアクセス~/Admin/Products.aspxInvalidCastExceptionすると、"型 'ASP.alternate_master' のオブジェクトを型 'ASP.site_master' にキャストできません" というメッセージが表示されたページ読み込み時にスローされます。

これらのエラーは、分離コード クラスに Site.master 、 で定義されていないパブリック イベント、プロパティ、およびメソッドが含まれているために Alternate.master発生します。 これら 2 つのページのマークアップ部分には、マスター ページを @MasterType 参照する ディレクティブがあります Site.master

<%@ MasterType VirtualPath="~/Site.master" %>

また、 の DetailsView の ItemInserted イベント ハンドラー ~/Admin/AddProduct.aspx には、緩やかに型指定された Page.Master プロパティを 型 Siteのオブジェクトにキャストするコードが含まれています。 @MasterTypeディレクティブ (この方法で使用) とイベント ハンドラーのItemInsertedキャストは、 ページと ~/Admin/Products.aspx ページを~/Admin/AddProduct.aspxマスター ページに密にSite.master結合します。

この緊密な結合を解除するために、パブリック メンバーの定義を含む共通の基底クラスを持ちSite.masterAlternate.master、そこから派生させることができます。 その後、 ディレクティブを更新して、 @MasterType この一般的な基本型を参照できます。

カスタム 基本マスター ページ クラスの作成

という名前BaseMasterPage.csのフォルダーに新しいクラス ファイルをApp_Code追加し、 からSystem.Web.UI.MasterPage派生させます。 では メソッドと プロパティBaseMasterPageRefreshRecentProductsGridGridMessageText定義する必要がありますが、これらのメンバーはマスター ページ (RecentProductsGridView と GridMessage Label) にSite.master固有の Web コントロールを使用するため、そこから移動Site.masterすることはできません。

必要なのは、これらのメンバーがそこで定義されるように構成BaseMasterPageすることですが、実際には の派生クラス (Site.masterAlternate.master) によってBaseMasterPage実装されます。 この種類の継承は、 クラスとそのメンバーを として abstractマークすることで可能です。 要するにabstract、これら 2 つのメンバーにキーワード (keyword)を追加すると、実装されていない RefreshRecentProductsGridGridMessageTextが読み上BaseMasterPageげられるが、その派生クラスは と読み上げられる。

また、 でBaseMasterPageイベントをPricesDoubled定義し、派生クラスによってイベントを発生させる手段を提供する必要があります。 この動作を容易にするために.NET Frameworkで使用されるパターンは、基底クラスにパブリック イベントを作成し、 virtual という名前OnEventNameの保護されたメソッドを追加することです。 その後、派生クラスは、このメソッドを呼び出してイベントを発生させたり、イベントが発生する直前または直後にコードを実行するようにオーバーライドしたりできます。

次のコードが含まれるようにクラスを更新します BaseMasterPage

using System; public abstract class BaseMasterPage : System.Web.UI.MasterPage
{ 
    public event EventHandler PricesDoubled; 
    protected virtual void OnPricesDoubled(EventArgs e) 
    { 
        if (PricesDoubled != null) 
        PricesDoubled(this, e); 
    } 
    public abstract void RefreshRecentProductsGrid();
    public abstract string GridMessageText 
    { 
        get; 
        set; 
    } 
}

次に、分離コード クラスに Site.master 移動し、 から BaseMasterPage派生させます。 では、 abstractSite.masterこれらのabstractメンバーをオーバーライドする必要があるためBaseMasterPageです。 メソッドとプロパティのoverride定義にキーワード (keyword)を追加します。 また、基本クラスOnPricesDoubledの メソッドのPricesDoubled呼び出しを使用して、DoublePriceButton のClickイベント ハンドラーでイベントを発生させるコードを更新します。

これらの変更の後、 Site.master 分離コード クラスには次のコードを含める必要があります。

public partial class Site : BaseMasterPage { 
    protected void Page_Load(object sender, EventArgs e) 
    { 
        DateDisplay.Text = DateTime.Now.ToString("dddd, MMMM dd"); 
    } 
    public override void RefreshRecentProductsGrid()
    { 
        RecentProducts.DataBind();
    } 
    public override string GridMessageText
    { 
        get 
        {
            return GridMessage.Text;
        } 
        set
        {
            GridMessage.Text = value; 
        } 
    }
    protected void DoublePrice_Click(object sender, EventArgs e) 
    { 
        // Double the prices 
        DoublePricesDataSource.Update();
        // Refresh RecentProducts 
        RecentProducts.DataBind();
        // Raise the PricesDoubled event
        base.OnPricesDoubled(EventArgs.Empty);
    } 
}

また、2 つのabstractメンバーからBaseMasterPage派生してオーバーライドするために、 の分離コード クラスを更新Alternate.masterする必要があります。 ただし、最新の製品を一覧表示する GridView や、新しい製品がデータベースに追加された後にメッセージを表示する Label が含まれていないため Alternate.master 、これらのメソッドは何もする必要はありません。

public partial class Alternate : BaseMasterPage 
{ 
    public override void RefreshRecentProductsGrid() 
    { 
        // Do nothing 
    } 
    public override string GridMessageText 
    { 
        get
        { 
            return string.Empty;
        } 
        set
        {
            // Do nothing 
        } 
    }
}

基本マスター ページ クラスの参照

クラスをBaseMasterPage完了し、2 つのマスター ページを拡張したので、最後の手順では、 ページと ~/Admin/Products.aspx ページを更新~/Admin/AddProduct.aspxして、この一般的な型を参照します。 最初に、両方のページの ディレクティブを @MasterType 次から変更します。

<%@ MasterType VirtualPath="~/Site.master" %>

移動先:

<%@ MasterType TypeName="BaseMasterPage" %>

プロパティは、ファイル パスを参照するのではなく、 @MasterType 基本型 (BaseMasterPage) を参照するようになりました。 したがって、両方のページの分離コード クラスで使用される厳密に型指定されたMasterプロパティは、型ではなく 型BaseMasterPageSiteになりました。 この変更に伴い、 を再検討してください ~/Admin/Products.aspx。 以前は、ページがマスター ページを使用Alternate.masterするように構成されていますが、 ディレクティブがファイルを参照Site.masterしているため、@MasterTypeキャスト エラーが発生しました。 しかし、ページがエラーなしでレンダリングされるようになりました。 これは、マスター ページを型BaseMasterPageAlternate.masterオブジェクトにキャストできるためです (拡張されているため)。

で行 ~/Admin/AddProduct.aspxう必要がある小さな変更が 1 つあります。 DetailsView コントロールの ItemInserted イベント ハンドラーでは、厳密に型指定されたプロパティと緩やかに型指定された Master プロパティの両方が使用されます Page.Master 。 ディレクティブを更新したときに厳密に型指定された参照を @MasterType 修正しましたが、緩やかに型指定された参照を更新する必要があります。 次のコード行を置き換えます。

Site myMasterPage = Page.Master as Site;

基本型にキャスト Page.Master する次のを使用します。

BaseMasterPage myMasterPage = Page.Master as BaseMasterPage;

手順 4: コンテンツ ページにバインドするマスター ページを決定する

現在、このクラスは BasePage 、ページ ライフサイクルの MasterPageFile PreInit ステージで、すべてのコンテンツ ページのプロパティをハードコーディングされた値に設定しています。 このコードを更新して、何らかの外部要素に基づいてマスター ページを作成できます。 読み込むマスター ページは、現在ログオンしているユーザーの設定によって異なる場合があります。 その場合は、 メソッドBasePageOnPreInit、現在アクセスしているユーザーのマスター ページ設定を検索するコードを記述する必要があります。

使用するマスター ページ (またはAlternate.master) をユーザーが選択できる Web ページをSite.master作成し、この選択内容を Session 変数に保存してみましょう。 まず、 という名前 ChooseMasterPage.aspxのルート ディレクトリに新しい Web ページを作成します。 このページ (またはそれ以降の他のコンテンツ ページ) を作成する場合、マスター ページは でプログラムによって設定されるため、マスター ページに BasePageバインドする必要はありません。 ただし、新しいページをマスター ページにバインドしない場合、新しいページの既定の宣言型マークアップには、Web フォームと、マスター ページによって提供されるその他のコンテンツが含まれます。 このマークアップを適切なコンテンツ コントロールに手動で置き換える必要があります。 そのため、新しい ASP.NET ページをマスター ページにバインドする方が簡単です。

注意

Alternate.master には ContentPlaceHolder コントロールのセットが同じであるためSite.master、新しいコンテンツ ページを作成するときに選択するマスター ページは関係ありません。 一貫性を保つには、 を使用 Site.masterすることをお勧めします。

Web サイトに新しいコンテンツ ページを追加する

図 05: Web サイトに新しいコンテンツ ページを追加する (フルサイズの画像を表示する をクリックします)

このレッスンの Web.sitemap エントリを含むようにファイルを更新します。 マスター ページの の下 <siteMapNode> に次のマークアップを追加し、AJAX レッスン ASP.NET します。

<siteMapNode url="~/ChooseMasterPage.aspx" title="Choose a Master Page" />

ページにコンテンツを追加するChooseMasterPage.aspx前に、ページの分離コード クラスを (ではなくSystem.Web.UI.Page) からBasePage派生するように更新します。 次に、DropDownList コントロールをページに追加し、そのプロパティを IDMasterPageChoice設定し、"~/Site.master" と "~/Alternate.master" の値を持つ Text 2 つの ListItems を追加します。

Button Web コントロールをページに追加し、その ID プロパティと Text プロパティをそれぞれ SaveLayout に設定し、それぞれ "レイアウトの選択を保存" に設定します。 この時点で、ページの宣言型マークアップは次のようになります。

<p> 
 Your layout choice: 
 <asp:DropDownList ID="MasterPageChoice" runat="server"> 
 <asp:ListItem>~/Site.master</asp:ListItem>
 <asp:ListItem>~/Alternate.master</asp:ListItem>
 </asp:DropDownList> 
</p> 
<p> 
 <asp:Button ID="SaveLayout" runat="server" Text="Save Layout Choice" /> 
</p>

ページに初めてアクセスするときは、ユーザーが現在選択しているマスター ページの選択肢を表示する必要があります。 イベント ハンドラーを Page_Load 作成し、次のコードを追加します。

protected void Page_Load(object sender, EventArgs e) 
{ 
    if (!Page.IsPostBack) 
    { 
        if (Session["MyMasterPage"] != null)
        {
            ListItem li = MasterPageChoice.Items.FindByText(Session["MyMasterPage"].ToString());
            if (li != null) 
                li.Selected = true; 
        } 
    }
}

上記のコードは、最初のページ アクセスでのみ実行されます (後続のポストバックでは実行されません)。 最初に、Session 変数 MyMasterPage が存在するかどうかを確認します。 その場合は、DropDownList で一致する ListItem を MasterPageChoice 検索しようとします。 一致する ListItem が見つかった場合、その Selected プロパティは に true設定されます。

また、ユーザーの選択を Session 変数に保存する MyMasterPage コードも必要です。 Button のイベントのイベント ハンドラーを SaveLayout 作成し、次の Click コードを追加します。

protected void SaveLayout_Click(object sender, EventArgs e)
{
    Session["MyMasterPage"] = MasterPageChoice.SelectedValue;
    Response.Redirect("ChooseMasterPage.aspx"); 
}

注意

イベント ハンドラーが Click ポストバックで実行される頃には、マスター ページは既に選択されています。 したがって、ユーザーのドロップダウン リストの選択は、次のページにアクセスするまで有効になりません。 は Response.Redirect 、ブラウザーに を強制的に要求 ChooseMasterPage.aspxします。

ページが ChooseMasterPage.aspx 完了したら、最後のタスクは BasePage Session 変数の MasterPageFile 値に基づいて プロパティを MyMasterPage 割り当てることです。 Session 変数が に設定されていない場合、既定値は BasePageSite.master設定されます。

protected override void OnPreInit(EventArgs e) 
{ 
    SetMasterPageFile();
    base.OnPreInit(e); 
} 
protected virtual void SetMasterPageFile()
{ 
    this.MasterPageFile = GetMasterPageFileFromSession();
} 
protected string GetMasterPageFileFromSession() 
{ 
    if (Session["MyMasterPage"] == null) 
        return "~/Site.master";
    else
        return Session["MyMasterPage"].ToString(); 
}

注意

オブジェクトMasterPageFileのプロパティを割り当てるコードをPageイベント ハンドラーから OnPreInit 2 つの異なるメソッドに移動しました。 この最初のメソッド は、 SetMasterPageFileプロパティを MasterPageFile 2 番目のメソッド GetMasterPageFileFromSession() によって返される値に割り当てます。 必要に応じて、拡張する将来のSetMasterPageFileクラスがBasePage必要に応じてそれをオーバーライドしてカスタム ロジックを実装できるように、 メソッドvirtualを作成しました。 次のチュートリアルでは、 の プロパティをオーバーライドするBasePageSetMasterPageFile例を示します。

このコードを配置した状態で、ページにアクセスします ChooseMasterPage.aspx 。 最初はマスター ページが Site.master 選択されていますが (図 6 を参照)、ユーザーはドロップダウン リストから別のマスター ページを選択できます。

Site.master マスター ページを使用してコンテンツ ページを表示する

図 06: マスター ページを使用してコンテンツ ページが Site.master 表示される (フルサイズの画像を表示するをクリックします)

Alternate.master マスター ページを使用してコンテンツ ページが表示されるようになりました

図 07: マスター ページを使用してコンテンツ ページが Alternate.master 表示されるようになりました (クリックするとフルサイズの画像が表示されます)

まとめ

コンテンツ ページにアクセスすると、そのコンテンツ コントロールはマスター ページの ContentPlaceHolder コントロールと融合されます。 コンテンツ ページのマスター ページは、 クラスの プロパティによってPage示されます。このプロパティは、初期化ステージ中に @Page ディレクティブの MasterPageFile 属性に割り当MasterPageFileてられます。 このチュートリアルで示したように、PreInit ステージの MasterPageFile 終了前であれば、 プロパティに値を割り当てることができます。 プログラムでマスター ページを指定できることで、外部要因に基づいてコンテンツ ページをマスター ページに動的にバインドするなど、より高度なシナリオの扉が開きます。

プログラミングに満足!

もっと読む

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

著者について

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

特別な感謝

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