Поделиться через


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

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

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

Введение

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

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

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

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

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

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

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

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

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

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

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

В начале этапа Page PreInit объект вызывает его PreInit событие и вызывает его OnPreInit метод. Чтобы задать эталонную страницу программным способом, можно создать обработчик событий для PreInit события или переопределить OnPreInit метод. Давайте рассмотрим оба метода.

Начните с открытия Default.aspx.csфайла класса code-behind для домашней страницы нашего сайта. Добавьте обработчик событий для события страницы 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 его. В этом примере давайте не задали главную страницу на определенной странице, а не из BasePage. Помните, что мы создали пользовательский базовый класс страницы (BasePage) обратно в руководстве по указанию заголовка, мета тегов и других заголовков HTML в руководстве по главной странице . BasePage В настоящее время переопределяет Page метод классаOnLoadComplete, где он задает свойство страницы Title на основе данных карты сайта. Давайте обновим BasePage метод, чтобы также переопределить OnPreInit метод, чтобы программно указать главную страницу.

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

Так как все страницы содержимого являются производными от BasePageних, все из них теперь назначаемой главной странице программным способом. На этом этапе 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 в конструкторе. Если вы вернетесь в Visual Studio и перейдите к Default.aspx конструктору, появится сообщение "Ошибка главной страницы: страница содержит элементы управления, требующие ссылки на эталонную страницу, но не указано" (см. рис. 2).

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

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

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

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

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

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

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

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

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

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

Примечание.

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

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

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

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

Главная Site.master страница включает четыре элемента управления ContentPlaceHolder:

  • head
  • MainContent
  • QuickLoginUI
  • LeftColumnContent

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

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

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

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

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

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

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

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

Добавьте новый файл класса в папку App_Code с именем BaseMasterPage.cs и наследуйте ее.System.Web.UI.MasterPage Нам нужно определить RefreshRecentProductsGrid метод и GridMessageText свойство, BaseMasterPageно мы не можем просто переместить их туда Site.master , так как эти элементы работают с веб-элементами управления, которые относятся к Site.master главной странице ( RecentProducts GridView и 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 code-behind и наследуйтесь от BaseMasterPageнего. Потому что BaseMasterPage abstract нам нужно переопределить эти abstract члены здесь Site.master. Добавьте ключевое override слово в определения методов и свойств. Также обновите код, который вызывает PricesDoubled событие в DoublePrice обработчике событий Button Click с вызовом метода базового класса OnPricesDoubled .

После этих изменений Site.master класс code-behind должен содержать следующий код:

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 класс и расширяли две главные страницы, мы завершаем его, чтобы обновить ~/Admin/AddProduct.aspx и ~/Admin/Products.aspx страницы, чтобы ссылаться на этот общий тип. Начните с изменения @MasterType директивы на обеих страницах:

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

Кому:

<%@ MasterType TypeName="BaseMasterPage" %>

Вместо ссылки на путь к @MasterType файлу свойство теперь ссылается на базовый тип (BaseMasterPage). Следовательно, строго типизированное Master свойство, используемое в классах кода обеих страниц, теперь имеет тип (вместо типа BaseMasterPage Site). С этим изменением на месте пересматривается ~/Admin/Products.aspx. Ранее это привело к ошибке приведения, так как страница настроена на использование главной Alternate.master страницы, но @MasterType директива ссылается на Site.master файл. Но теперь страница отрисовывается без ошибок. Это связано с тем, что эталонная Alternate.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 на жестко закодированное значение на этапе предварительной версии жизненного цикла страницы. Этот код можно обновить, чтобы создать эталонную страницу на некоторых внешних факторах. Возможно, эталонная страница для загрузки зависит от настроек текущего пользователя, вошедшего в систему. В этом случае нам потребуется написать код в методе OnPreInit , BasePage который ищет параметры главной страницы пользователя.

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

Примечание.

Так как Site.master и один и Alternate.master тот же набор элементов управления ContentPlaceHolder, не имеет значения главной страницы при создании новой страницы содержимого. Для согласованности я бы предложил использовать 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 на страницу и задайте для нее значения 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; 
        } 
    }
}

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

Нам также нужен код, который сохраняет выбор пользователя в переменную сеанса MyMasterPage . Создайте обработчик событий для SaveLayout события Button 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 назначить MasterPageFile свойство в зависимости от значения переменной сеансаMyMasterPage. Если переменная сеанса не задана 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 Изначально выбрана эталонная страница (см. рис. 6), но пользователь может выбрать другую главную страницу из раскрывающегося списка.

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

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

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

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

Итоги

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

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

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

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

Об авторе

Скотт Митчелл, автор нескольких книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с технологиями Microsoft Web с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга Сэмс Учит себя ASP.NET 3,5 в 24 часах. Скотт можно получить по mitchell@4GuysFromRolla.com адресу или через свой блог.http://ScottOnWriting.NET

Особое спасибо

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