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

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

Проверяет настройку страницы 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 имеет чистый эффект от назначения Pageсвойства на MasterPageFile этапе инициализации, который является самым первым этапом жизненного цикла страницы. Можно также задать это свойство программным способом. Однако необходимо, чтобы это свойство было задано до слияния на рис. 1.

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

Начните с открытия Default.aspx.vbфайла класса кода программной части для домашней страницы нашего сайта. Добавьте обработчик событий для события страницы, PreInit введя следующий код:

Protected Sub Page_PreInit(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreInit 
End Sub

Здесь можно задать MasterPageFile свойство . Обновите код таким образом, чтобы он присваивал значение "~/Site. master" в MasterPageFile свойство .

Protected Sub Page_PreInit(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreInit 
 Me.MasterPageFile = "~/Site.master"
End Sub

Если вы задали точку останова и начали с отладки, вы увидите, что при каждом Default.aspx посещении страницы или при отправке обратной передачи на эту страницу Page_PreInit обработчик событий выполняется и MasterPageFile свойство назначается "~/Site.master".

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

Protected Overrides Sub OnPreInit(ByVal e As System.EventArgs)
 Me.MasterPageFile = "~/Site.master" 
 MyBase.OnPreInit(e)
End Sub

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

Как насчет директивы@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 (и, в своюихе, и, в свою 2018 году, на страницах содержимого). На рисунке 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.maser", а затем перейдите на веб-сайт. Каждая страница должна работать без ошибок, за исключением двух: ~/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.vb и наследуйте его от System.Web.UI.MasterPage. Нам нужно определить RefreshRecentProductsGrid метод и GridMessageText свойство в BaseMasterPage, но мы не можем просто переместить их оттудаSite.master, так как эти элементы работают с веб-элементами управления, характерными для Site.master страницы master (RecentProductsGridView и GridMessage Label).

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

Кроме того, необходимо определить PricesDoubled событие в BaseMasterPage и предоставить средства для создания события с помощью производных классов. Шаблон, используемый в платформа .NET Framework для упрощения этого поведения, заключается в создании открытого события в базовом классе и добавлен защищенный переопределенный метод с именем OnEventName. Производные классы могут вызывать этот метод для вызова события или переопределять его для выполнения кода непосредственно перед или после возникновения события.

Обновите BaseMasterPage класс таким образом, чтобы он содержал следующий код:

Public MustInherit Class BaseMasterPage 
 Inherits System.Web.UI.MasterPage 
 Public Event PricesDoubled As EventHandler
 Protected Overridable Sub OnPricesDoubled(ByVal e As EventArgs)
 RaiseEvent PricesDoubled(Me, e)
 End Sub
 Public MustOverride Sub RefreshRecentProductsGrid() 
 Public MustOverride Property GridMessageText() As String 
End Class

Затем перейдите к классу Site.master кода программной части и наследуйте его от BaseMasterPage. Так как BaseMasterPage содержит элементы, помеченные MustOverride , необходимо переопределить эти члены здесь в Site.master. Overrides Добавьте ключевое слово в определения метода и свойства. Кроме того, обновите код, который вызывает PricesDoubled событие в DoublePrice обработчике Click событий Button, вызвав метод базового класса OnPricesDoubled .

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

Partial Class Site 
 Inherits BaseMasterPage
 Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
 DateDisplay.Text = DateTime.Now.ToString("dddd, MMMM dd")
 End Sub
 Public Overrides Sub RefreshRecentProductsGrid() 
 RecentProducts.DataBind()
 End Sub 
 Public Overrides Property GridMessageText() As String 
 Get
 Return GridMessage.Text
 End Get 
 Set(ByVal Value As String) 
 GridMessage.Text = Value 
 End Set
 End Property 
 Protected Sub DoublePrice_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles DoublePrice.Click 
 ' Double the prices 
 DoublePricesDataSource.Update()
 ' Refresh RecentProducts 
 RecentProducts.DataBind()
 ' Raise the PricesDoubled event
 MyBase.OnPricesDoubled(EventArgs.Empty)
 End Sub 
End Class

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

Partial Class Alternate 
 Inherits BaseMasterPage
 Public Overrides Property GridMessageText() As String 
 Get
 Return String.Empty
 End Get
 Set(ByVal value As String) 
 ' Do nothing 
 End Set 
 End Property 
 Public Overrides Sub RefreshRecentProductsGrid()
 ' Do nothing 
 End Sub 
End Class

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

Теперь, когда мы завершили работу с классом 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 директивы, но нам по-прежнему нужно обновить слабо типизированную ссылку. Замените следующую строку кода:

Dim myMasterPage As Site = CType(Page.Master, Site)

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

Dim myMasterPage As BaseMasterPage = CType(Page.Master, 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 Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
 If Not Page.IsPostBack Then 
 If Session("MyMasterPage") IsNot Nothing Then 
 Dim li As ListItem = MasterPageChoice.Items.FindByText(Session("MyMasterPage").ToString())
 If li IsNot Nothing Then 
 li.Selected = True
 End If 
 End If 
 End If 
End Sub

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

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

Protected Sub SaveLayout_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SaveLayout.Click 
 Session("MyMasterPage") = MasterPageChoice.SelectedValue 
 Response.Redirect("ChooseMasterPage.aspx")
End Sub

Примечание

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

ChooseMasterPage.aspx После завершения страницы наша конечная задача — BasePage назначить MasterPageFile свойство на основе значения переменной MyMasterPage Session. Если переменная Session не задана, по умолчанию имеет BasePage значение Site.master.

Protected Overrides Sub OnPreInit(ByVal e As System.EventArgs)
 SetMasterPageFile() 
 MyBase.OnPreInit(e)
End Sub 
Protected Overridable Sub SetMasterPageFile() 
 Me.MasterPageFile = GetMasterPageFileFromSession() 
End Sub 
Protected Function GetMasterPageFileFromSession() As String 
 If Session("MyMasterPage") Is Nothing Then
 Return "~/Site.master"
 Else 
 Return Session("MyMasterPage").ToString() 
 End If 
End Function

Примечание

Я переместил код, который назначает Page свойство объекта MasterPageFile из обработчика OnPreInit событий и в два отдельных метода. Этот первый метод, SetMasterPageFile, присваивает MasterPageFile свойство значению, возвращаемого вторым методом . GetMasterPageFileFromSession Я помечал SetMasterPageFile метод Overridable , чтобы будущие классы, расширяющие 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