Программное указание эталонной страницы (C#)

Скотт Митчелл

Проверяет настройку страницы master содержимого программным способом с помощью обработчика событий PreInit.

Введение

После первого примера в статье Создание макета Site-Wide с помощью главных страниц все страницы контента декларативно ссылаются на свою master страницу с помощью атрибута MasterPageFile в директиве @Page . Например, следующая @Page директива связывает страницу содержимого со страницей Site.mastermaster :

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

КлассPage в System.Web.UI пространстве имен содержит MasterPageFile свойство , которое возвращает путь к странице master страницы содержимого. Именно это свойство задается директивой @Page . Это свойство также можно использовать для программного указания страницы master содержимого. Этот подход полезен, если вы хотите динамически назначать страницу master на основе внешних факторов, таких как пользователь, посещающий страницу.

В этом руководстве мы добавим вторую страницу master на веб-сайт и динамически решаем, какую страницу master использовать во время выполнения.

Шаг 1. Обзор жизненного цикла страницы

Всякий раз, когда на веб-сервер поступает запрос на страницу ASP.NET, которая является страницей содержимого, подсистема ASP.NET должна объединить элементы управления контентом страницы в соответствующие элементы управления ContentPlaceHolder master страницы. Это слияние создает единую иерархию элементов управления, которая затем может проходить через типичный жизненный цикл страницы.

На рисунке 1 показана эта слияние. На шаге 1 на рис. 1 показано начальное содержимое и иерархии master элементов управления страницы. В конце этапа PreInit элементы управления контентом на странице добавляются в соответствующий объект ContentPlaceHolders на странице master (шаг 2). После этого слияния страница master служит корнем иерархии плавленного элемента управления. Затем эта слитая иерархия элементов управления добавляется на страницу для создания окончательной иерархии элементов управления (шаг 3). Результатом является то, что иерархия элементов управления страницы включает в себя иерархию слитых элементов управления.

Иерархии элементов управления главной страницы и контентной страницы объединяются на этапе preInit

Рис. 01. Иерархии элементов управления главной страницы и страницы содержимого объединяются на этапе preInit (щелкните для просмотра полноразмерного изображения)

Шаг 2. ЗаданиеMasterPageFileсвойства из кода

Какие master страницы участвуют в этом слиянии, зависит от значения Page свойства объектаMasterPageFile. Задание атрибута MasterPageFile в директиве @Page имеет чистый эффект назначения PageMasterPageFile свойства на этапе инициализации, который является самым первым этапом жизненного цикла страницы. Можно также задать это свойство программным способом. Однако крайне важно, чтобы это свойство было задано до слияния на рис. 1.

В начале этапа Page PreInit объект вызывает событиеPreInit и вызывает методOnPreInit . Чтобы задать master страницу программным способом, можно либо создать обработчик событий для 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 посещении страницы или при обратной отправке на эту страницу обработчик событий выполняется, Page_PreInit а свойству MasterPageFile присваивается "~/Site.master".

Кроме того, можно переопределить Page метод класса OnPreInit и задать в нем MasterPageFile свойство . В этом примере давайте не задавайте master страницу на определенной странице, а из BasePage. Помните, что мы создали пользовательский класс базовой страницы (BasePage) еще в руководстве Указание заголовка, метатегов и других заголовков HTML в главной странице . В настоящее BasePage время переопределяет Page метод класса OnLoadComplete , где он задает свойство страницы Title на основе данных карты сайта. Давайте обновимBasePage, чтобы переопределить OnPreInit метод для программного указания страницы master.

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

Так как все страницы содержимого являются производными от BasePage, все они теперь имеют master страницы, назначенные программным способом. На этом этапе PreInit обработчик событий в Default.aspx.cs является лишним. Вы можете удалить его.

Как насчет директивы@Page?

Что может быть немного запутанным, так это то, что свойства страниц содержимого MasterPageFile теперь указываются в двух местах: программно в BasePage методе OnPreInit класса, а также с помощью MasterPageFile атрибута в директиве каждой страницы содержимого @Page .

Первым этапом жизненного цикла страницы является этап инициализации. На этом этапе свойству Page объекта MasterPageFile присваивается значение атрибута MasterPageFile в директиве @Page (если оно указано). Этап PreInit следует за этапом инициализации, и именно здесь мы программно задаем Page свойство объекта MasterPageFile , тем самым перезаписав значение, присвоенное директивой @Page . Так как мы задаем Page свойство объекта MasterPageFile программным способом, мы можем удалить MasterPageFile атрибут из @Page директивы, не влияя на взаимодействие с конечным пользователем. Чтобы убедиться в этом, удалите MasterPageFile атрибут из директивы @Page в , Default.aspx а затем перейдите на страницу через браузер. Как и следовало ожидать, выходные данные будут теми же, что и до удаления атрибута.

MasterPageFile Указывает, задано ли свойство с помощью @Page директивы или программным способом, не имеет значения для взаимодействия с конечным пользователем. MasterPageFile Однако атрибут в директиве @Page используется Visual Studio во время разработки для создания представления WYSIWYG в Designer. Если вернуться к Default.aspx в Visual Studio и перейти к Designer появится сообщение "Ошибка главной страницы: страница содержит элементы управления, требующие ссылки на эталонную страницу, но не указан" (см. рис. 2).

Короче говоря, необходимо оставить MasterPageFile атрибут в директиве , @Page чтобы использовать широкие возможности разработки в Visual Studio.

Visual Studio Использует атрибут MasterPageFile директивы <span class=@Page для отображения представления конструктора" />

Рис. 02. Visual Studio использует @Page атрибут директивы для отображения представления конструктора MasterPageFile (щелкните, чтобы просмотреть полноразмерное изображение)

Шаг 3. Создание альтернативной главной страницы

Так как master страницу содержимого можно задать программно во время выполнения, можно динамически загружать определенную страницу master на основе некоторых внешних критериев. Эта функция может быть полезна в ситуациях, когда макет сайта должен меняться в зависимости от пользователя. Например, веб-приложение подсистемы блога может позволить пользователям выбирать макет для своего блога, где каждый макет связан с другой master страницей. Во время выполнения, когда посетитель просматривает блог пользователя, веб-приложению потребуется определить макет блога и динамически связать соответствующую страницу master со страницей содержимого.

Давайте рассмотрим, как динамически загружать страницу master во время выполнения на основе некоторых внешних критериев. Наш веб-сайт в настоящее время содержит только одну страницу master (Site.master). Нам нужна другая страница master, чтобы проиллюстрировать выбор страницы master во время выполнения. Этот шаг посвящен созданию и настройке новой страницы master. На шаге 4 рассматривается определение master страницы для использования во время выполнения.

Создайте новую страницу master в корневой папке с именем Alternate.master. Также добавьте новую таблицу стилей на веб-сайт с именем AlternateStyles.css.

Добавление другой главной страницы и CSS-файла на веб-сайт

Рис. 03. Добавление другой главной страницы и CSS-файла на веб-сайт (щелкните для просмотра полноразмерного изображения)

Я разработал страницу Alternate.master master, чтобы заголовок отображался в верхней части страницы, по центру и на фоне военно-морского флота. Я отбрасывал левый столбец и переместил это содержимое под MainContent элементом управления ContentPlaceHolder, который теперь охватывает всю ширину страницы. Кроме того, я переместил неупорядоченный список уроков и заменил его горизонтальным списком над MainContent. Я также обновил шрифты и цвета, используемые на странице master (и, в расширении, на страницах содержимого). На рисунке 4 показано Default.aspx использование страницы Alternate.master master.

Примечание

ASP.NET включает возможность определения тем. Тема — это коллекция изображений, CSS-файлов и параметров свойств веб-элемента управления, связанных со стилем, которые можно применить к странице во время выполнения. Темы — это путь, если макеты сайта отличаются только отображаемыми изображениями и правилами CSS. Если макеты отличаются более существенно, например с использованием различных веб-элементов управления или с совершенно другим макетом, вам потребуется использовать отдельные master страницы. Дополнительные сведения о темах см. в разделе Дальнейшее чтение в конце этого руководства.

Наши страницы содержимого теперь могут использовать новый внешний вид

Рис. 04. Наши страницы содержимого теперь могут использовать новый внешний вид (щелкните для просмотра полноразмерного изображения)

При слиянии разметки страниц master и содержимого класс проверяет, MasterPage ссылается ли каждый элемент управления Контентом на странице содержимого на ContentPlaceHolder на странице master. Исключение возникает при обнаружении элемента управления контентом, который ссылается на несуществующий ContentPlaceHolder. Иными словами, крайне важно, чтобы страница master, назначаемая странице содержимого, была contentPlaceHolder для каждого элемента управления контентом на странице содержимого.

Страница Site.master master содержит четыре элемента управления ContentPlaceHolder:

  • head
  • MainContent
  • QuickLoginUI
  • LeftColumnContent

Некоторые страницы содержимого на нашем веб-сайте содержат только один или два элемента управления контентом; другие включают элемент управления Контент для каждого из доступных ContentPlaceHolders. Если наша новая страница master (Alternate.master) может когда-либо быть назначена тем страницам содержимого, которые имеют элементы управления контентом для всех ContentPlaceHolders в Site.master , важно также включить те же элементы управления ContentPlaceHolder, что Alternate.master и Site.master.

Alternate.master Чтобы страница master выглядела аналогично моей (см. рис. 4), начните с определения стилей страницы master в таблице стилей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 значениями, что и элементы управления ContentPlaceHolder в Site.master. Кроме того, он включает элемент управления ScriptManager, необходимый для тех страниц на нашем веб-сайте, которые используют платформу ASP.NET AJAX.

<!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>

Тестирование новой главной страницы

Чтобы протестировать эту новую master странице обновите BasePage метод классаOnPreInit, чтобы свойству MasterPageFile было присвоено значение "~/Alternate.master", а затем посетите веб-сайт. Каждая страница должна работать без ошибок, за исключением двух: ~/Admin/AddProduct.aspx и ~/Admin/Products.aspx. Добавление продукта в DetailsView в ~/Admin/AddProduct.aspx приводит к получению NullReferenceException из строки кода, которая пытается задать свойство страницы GridMessageText master. При посещении ~/Admin/Products.aspxInvalidCastException возникает при загрузке страницы сообщение: "Не удается привести объект типа "ASP.alternate_master" к типу "ASP.site_master".

Эти ошибки возникают из-за того Site.master , что класс кода программной части содержит открытые события, свойства и методы, которые не определены в Alternate.master. Часть разметки этих двух страниц имеет директиву@MasterType, которая ссылается на Site.master master страницу.

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

Кроме того, обработчик событий DetailsView ItemInserted в ~/Admin/AddProduct.aspx содержит код, который приводит свойство слабо типизированного Page.Master к объекту типа Site. Директива @MasterType (используется таким образом) и приведение в обработчике ItemInserted событий тесно связаны ~/Admin/AddProduct.aspx страницы и ~/Admin/Products.aspx со страницей Site.master master.

Чтобы разорвать эту тесную связь, мы можем получить Site.master и Alternate.master наследовать от общего базового класса, который содержит определения для открытых членов. После этого можно обновить директиву для @MasterType ссылки на этот общий базовый тип.

Создание настраиваемого класса базовой главной страницы

Добавьте новый файл класса в папку с App_Code именем BaseMasterPage.cs и наследуйте его от System.Web.UI.MasterPage. Нам нужно определить RefreshRecentProductsGrid метод и GridMessageText свойство в BaseMasterPage, но мы не можем просто переместить их оттудаSite.master, так как эти элементы работают с веб-элементами управления, характерными для Site.master страницы master (RecentProductsGridView и GridMessage Label).

Нам нужно настроить BaseMasterPage таким образом, чтобы эти члены были определены там, но на самом деле реализуются производными классами BaseMasterPage(Site.master и Alternate.master). Этот тип наследования возможен, помечая класс и его члены как abstract. Короче говоря, при добавлении abstract ключевое слово к этим двум элементам объявляется, что BaseMasterPage не реализованы RefreshRecentProductsGrid и GridMessageText, но что производные от него классы будут.

Кроме того, необходимо определить PricesDoubled событие в BaseMasterPage и предоставить средства для создания события с помощью производных классов. Шаблон, используемый в платформа .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. Потому что BaseMasterPage нам нужно переопределить эти abstract члены здесь, в Site.master.abstract override Добавьте ключевое слово в определения метода и свойства. Кроме того, обновите код, который вызывает PricesDoubled событие в DoublePrice обработчике Click событий Button, вызвав метод базового класса OnPricesDoubled .

После этих изменений 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);
    } 
}

Кроме того, необходимо обновить Alternate.masterкласс кода программной части, чтобы он был производным от BaseMasterPage двух abstract членов и переопределен. Но поскольку Alternate.master не содержит GridView, в котором перечислены последние продукты, и метки, отображающей сообщение после добавления нового продукта в базу данных, эти методы не должны ничего делать.

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

Ссылка на класс базовой главной страницы

Теперь, когда мы завершили работу с классом BaseMasterPage и расширили его две страницы master, наш последний шаг — обновить ~/Admin/AddProduct.aspx страницы и , ~/Admin/Products.aspx чтобы они ссылались на этот распространенный тип. Начните с изменения директивы на @MasterType обеих страницах с:

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

В:

<%@ MasterType TypeName="BaseMasterPage" %>

Вместо ссылки на путь к файлу @MasterType свойство теперь ссылается на базовый тип (BaseMasterPage). Следовательно, строго типизированное Master свойство, используемое в классах кода программной части обеих страниц, теперь имеет тип BaseMasterPage (а не тип Site). С этим изменением на месте вернитесь к ~/Admin/Products.aspx. Ранее это приводило к ошибке приведения, так как страница настроена для использования Alternate.master master страницы, но директива @MasterType ссылалась на Site.master файл. Но теперь страница отображается без ошибок. Это связано с тем Alternate.master , что master страницу можно привести к объекту типа BaseMasterPage (так как он расширяет его).

Существует одно небольшое изменение, которое необходимо внести в ~/Admin/AddProduct.aspx. Обработчик событий элемента управления ItemInserted DetailsView использует как строго типизированное Master , так и слабо типизированное Page.Master свойство. Мы исправили строго типизированную ссылку при обновлении @MasterType директивы, но нам по-прежнему нужно обновить слабо типизированную ссылку. Замените следующую строку кода:

Site myMasterPage = Page.Master as Site;

С помощью следующего, который приводит Page.Master к базовому типу:

BaseMasterPage myMasterPage = Page.Master as BaseMasterPage;

Шаг 4. Определение главной страницы для привязки к страницам содержимого

В настоящее время наш BasePage класс задает свойства всех страниц MasterPageFile содержимого как жестко закодированное значение на этапе PreInit жизненного цикла страницы. Мы можем обновить этот код, чтобы на странице master учитывались некоторые внешние факторы. Возможно, загрузка страницы master зависит от предпочтений текущего пользователя, выполнившего вход. В этом случае нам потребуется написать код в методе OnPreInit в BasePage , который ищет параметры страницы master текущего пользователя.

Давайте создадим веб-страницу, которая позволяет пользователю выбрать, какую master страницу использовать ( Site.master или Alternate.master ) и сохранить этот вариант в переменной сеанса. Начните с создания новой веб-страницы в корневом каталоге с именем ChooseMasterPage.aspx. При создании этой страницы (или любых других страниц содержимого в настоящее время) ее не нужно привязывать к master странице, так как master страница задается программным способом в BasePage. Однако если не привязать новую страницу к master странице, декларативная разметка новой страницы по умолчанию будет содержать веб-форму и другое содержимое, предоставляемое master страницей. Вам потребуется вручную заменить эту разметку соответствующими элементами управления контентом. По этой причине мне проще привязать новую страницу ASP.NET к master странице.

Примечание

Так как Site.master и Alternate.master имеют одинаковый набор элементов управления ContentPlaceHolder, не имеет значения, какую master страницу вы выбираете при создании новой страницы содержимого. Для обеспечения согласованности я бы предложил использовать .Site.master

Добавление страницы нового содержимого на веб-сайт

Рис. 05. Добавление новой страницы содержимого на веб-сайт (щелкните для просмотра полноразмерного изображения)

Обновите файл, Web.sitemap чтобы включить запись для этого урока. Добавьте следующую разметку под элементом для урока <siteMapNode> "Главные страницы" и ASP.NET AJAX:

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

Перед добавлением содержимого на страницу ChooseMasterPage.aspx обновите класс кода программной части страницы, чтобы он был производным от BasePage (а не System.Web.UI.Page). Затем добавьте элемент управления DropDownList на страницу, задайте для его ID свойства MasterPageChoiceзначение и добавьте два Элемента ListItems со значениями Text "~/Site.master" и "~/Alternate.master".

Добавьте на страницу элемент управления Button Web и задайте для его ID свойств SaveLayout и Text значение и "Сохранить вариант макета" соответственно. На этом этапе декларативная разметка страницы должна выглядеть примерно так:

<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>

При первом посещении страницы необходимо отобразить выбранный пользователем master выбор страницы. Создайте 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; 
        } 
    }
}

Приведенный выше код выполняется только при первом посещении страницы (а не при последующих обратных операциях). Сначала проверяется, существует ли переменная MyMasterPage Session. Если это так, он пытается найти соответствующий ListItem в MasterPageChoice DropDownList. Если найден соответствующий Объект ListItem, его Selected свойству trueприсваивается значение .

Нам также нужен код, который сохраняет выбор пользователя в переменной MyMasterPage Session. Создайте обработчик событий для SaveLayout события Button Click и добавьте следующий код:

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

Примечание

К тому времени, когда Click обработчик событий будет выполняться при обратной отправке, страница master уже была выбрана. Таким образом, выбор раскрывающегося списка пользователя не будет действовать до следующего посещения страницы. Заставляет Response.Redirect браузер повторно запрашивать ChooseMasterPage.aspx.

ChooseMasterPage.aspx После завершения страницы наша конечная задача — BasePage назначить MasterPageFile свойство на основе значения переменной MyMasterPage Session. Если переменная Session не задана, по умолчанию имеет BasePage значение Site.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(); 
}

Примечание

Я переместил код, который назначает Page свойство объекта MasterPageFile из обработчика OnPreInit событий и в два отдельных метода. Этот первый метод, SetMasterPageFile, присваивает MasterPageFile свойство значению, возвращаемого вторым методом . GetMasterPageFileFromSession Я сделал метод virtual таким SetMasterPageFile образом, чтобы будущие классы, расширяющие BasePage его, при необходимости могли переопределить его для реализации пользовательской логики. Пример переопределения BasePageSetMasterPageFile свойства мы рассмотрим в следующем руководстве.

После этого кода перейдите на страницу ChooseMasterPage.aspx . Изначально выбрана Site.master страница master (см. рис. 6), но пользователь может выбрать другую страницу master из раскрывающегося списка.

Страницы содержимого отображаются с помощью сайта. Эталонная страница master

Рис. 06. Страница содержимого отображается с помощью главной Site.master страницы (щелкните для просмотра полноразмерного изображения)

Страницы содержимого теперь отображаются с помощью альтернативного. Эталонная страница master

Рис. 07. Страницы содержимого теперь отображаются с помощью главной Alternate.master страницы (щелкните для просмотра полноразмерного изображения)

Сводка

При посещении страницы содержимого ее элементы управления контентом сливаются с элементами управления ContentPlaceHolder master страницы. Страница master страницы содержимого обозначается свойством Page класса MasterPageFile , которое назначается атрибуту @Page директивы MasterPageFile на этапе инициализации. Как показано в этом руководстве, мы можем присвоить значение свойству MasterPageFile до завершения этапа PreInit. Возможность программно указать страницу master открывает возможности для более сложных сценариев, таких как динамическая привязка страницы содержимого к странице master на основе внешних факторов.

Счастливое программирование!

Дополнительные материалы

Дополнительные сведения по темам, рассматриваемым в этом руководстве, см. в следующих ресурсах:

Об авторе

Скотт Митчелл (Scott Mitchell), автор нескольких книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с веб-технологиями Майкрософт с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга Sams Teach Yourself ASP.NET 3,5 в 24 часа. Скотт можно связаться по адресу mitchell@4GuysFromRolla.com или через его блог по адресу http://ScottOnWriting.NET.

Отдельная благодарность

Эта серия учебников была проверена многими полезными рецензентами. Ведущим рецензентом этого руководства был Сучи Банерджи. Хотите ознакомиться с моими предстоящими статьями MSDN? Если да, бросить мне линию на mitchell@4GuysFromRolla.com