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


Вложенные эталонные страницы (C#)

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

Показывает, как вложить одну главную страницу в другую.

Введение

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

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

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

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

Можно создать такие настраиваемые макеты с помощью вложенных главных страниц. Для реализации приведенного выше сценария мы создадим эталонную страницу, определяющую макет на уровне сайта, содержимое меню и нижнего колонтитула с contentPlaceHolders, определяющими настраиваемые регионы. Затем мы создадим три вложенных главных страницы, по одному для каждого типа веб-страницы. Каждая вложенная эталонная страница определяет содержимое среди типов страниц контента, использующих главную страницу. Другими словами, вложенная эталонная страница для страниц содержимого для конкретного пациента будет включать разметку и программную логику для отображения сведений об редактируемом пациенте. При создании новой страницы для конкретного пациента мы привязываем ее к этой вложенной главной странице.

Это руководство начинается с выделения преимуществ вложенных главных страниц. Затем показано, как создавать и использовать вложенные главные страницы.

Примечание.

Вложенные главные страницы были возможны с версии 2.0 платформа .NET Framework. Однако Visual Studio 2005 не включал поддержку времени разработки для вложенных главных страниц. Хорошая новость заключается в том, что Visual Studio 2008 предлагает широкий опыт разработки для вложенных главных страниц. Если вы хотите использовать вложенные эталонные страницы, но по-прежнему используете Visual Studio 2005, ознакомьтесь с записью блога Скотта Гатри, советы по вложенным эталонным страницам в VS 2005 времени разработки.

Преимущества вложенных главных страниц

Многие веб-сайты имеют переопределяющий дизайн сайта, а также более настраиваемые макеты, относящиеся к определенным типам страниц. Например, в демонстрационном веб-приложении мы создали раздел администрирования (страницы в папке ~/Admin ). В настоящее время веб-страницы в ~/Admin папке используют ту же главную страницу, что и те страницы, которые не находятся в разделе администрирования (а именно или Site.master Alternate.masterв зависимости от выбора пользователя).

Примечание.

На данный момент, притворяйтесь, что наш сайт имеет только одну главную страницу, Site.master. Мы будем использовать вложенные главные страницы с двумя (или более) эталонными страницами, начиная с раздела "Использование вложенной главной страницы для раздела администрирования" далее в этом руководстве.

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

  1. Вручную добавьте сведения об администрирования и ссылки на каждую страницу содержимого в папке ~/Admin .
  2. Site.master Обновите эталонную страницу, чтобы включить сведения и ссылки для раздела администрирования, а затем добавьте код на главную страницу, чтобы отобразить или скрыть эти разделы на основе того, просматривается ли одна из страниц администрирования.
  3. Создайте главную страницу специально для раздела администрирования, скопируйте разметку из Site.master, добавьте сведения и ссылки для раздела администрирования, а затем обновите страницы содержимого в папке ~/Admin , чтобы использовать эту новую эталонную страницу.
  4. Создайте вложенную главную страницу, которая привязывается Site.master и содержит страницы содержимого в папке ~/Admin , используйте эту новую вложенную главную страницу. Эта вложенная эталонная страница будет содержать только дополнительные сведения и ссылки, относящиеся к страницам администрирования, и не потребуется повторять разметку, уже определенную в Site.master.

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

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

Четвертый вариант, вложенные главные страницы, дает нам лучшие из второго и третьего вариантов. Сведения о макете на уровне сайта хранятся в одном файле — главной странице верхнего уровня, а содержимое, относящегося к определенным регионам, отделяется от разных файлов.

В этом руководстве рассматривается создание и использование простой вложенной главной страницы. Мы создадим новую эталонную страницу верхнего уровня, две вложенные главные страницы и две страницы содержимого. Начиная с статьи "Использование вложенной главной страницы для раздела администрирования", мы рассмотрим обновление существующей архитектуры главной страницы, чтобы включить использование вложенных главных страниц. В частности, мы создадим вложенную главную страницу и используем ее для включения дополнительного пользовательского содержимого для страниц содержимого в папку ~/Admin .

Шаг 1. Создание простой главной страницы верхнего уровня

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

Создайте новую папку с именем NestedMasterPages Simple.master, а затем добавьте в нее новый главный файл страницы. (См. рисунок 1 для снимка экрана Обозреватель решений после добавления этой папки и файла.) Перетащите файл таблицы стилей AlternateStyles.css из Обозреватель решений в конструктор. При этом элемент добавляется <link> в файл таблицы стилей в <head> элементе, после чего разметка элемента главной страницы <head> должна выглядеть следующим образом:

<head runat="server">
 <title>Untitled Page</title> 
 <asp:ContentPlaceHolder id="head" runat="server"> 
 </asp:ContentPlaceHolder>
 <link href="../AlternateStyles.css" rel="stylesheet" type="text/css" /> 
</head>

Затем добавьте следующую разметку в веб-форме Simple.master:

<div id="topContent"> 
 <asp:HyperLink ID="lnkHome" runat="server" 
 NavigateUrl="~/NestedMasterPages/Default.aspx"
 Text="Nested Master Pages Tutorial (Simple)" /> 
</div> 
<div id="mainContent"> 
 <asp:ContentPlaceHolder id="MainContent" runat="server"> 
 </asp:ContentPlaceHolder>
</div>

Эта разметка отображает ссылку "Вложенные главные страницы (простые)" в верхней части страницы в большом белом шрифте на фоне военно-морского флота. Под этим находится MainContent ContentPlaceHolder. На рисунке 1 показана эталонная Simple.master страница при загрузке в конструктор Visual Studio.

Эталонная страница простой точки при загрузке в конструктор Visual Studio.

Рис. 01. Вложенная главная страница определяет содержимое для страниц в разделе администрирования (щелкните, чтобы просмотреть изображение полного размера)

Шаг 2. Создание простой вложенной главной страницы

Simple.master содержит два элемента управления ContentPlaceHolder: MainContent ContentPlaceHolder, добавленный в веб-форму, вместе с head ContentPlaceHolder в элементе <head> . Если бы мы создали страницу содержимого и привязать ее к Simple.master странице содержимого, будет иметь два элемента управления "Содержимое", ссылающиеся на два ContentPlaceHolders. Аналогичным образом, если мы создадим вложенную главную страницу и привязываем ее к Simple.master ней, вложенная главная страница будет иметь два элемента управления Content.

Давайте добавим новую вложенную главную страницу в папку NestedMasterPages с именем SimpleNested.master. Щелкните правой кнопкой мыши папку NestedMasterPages и выберите пункт "Добавить новый элемент". Откроется диалоговое окно "Добавление нового элемента", показанное на рис. 2. Выберите тип шаблона главной страницы и введите имя новой главной страницы. Чтобы указать, что новая эталонная страница должна быть вложенной главной страницей, установите флажок "Выбрать главную страницу".

Затем нажмите кнопку "Добавить". Откроется то же диалоговое окно "Выбор главной страницы", которое отображается при привязке страницы содержимого к главной странице (см. рис. 3). Выберите главную Simple.master страницу в папке NestedMasterPages и нажмите кнопку "ОК".

Примечание.

Если вы создали веб-сайт ASP.NET с помощью модели проекта веб-приложения, а не модели проекта веб-сайта, флажок "Выбор главной страницы" в диалоговом окне "Добавление нового элемента", показанном на рис. 2. Чтобы создать вложенную главную страницу при использовании модели проекта веб-приложения, необходимо выбрать шаблон вложенной главной страницы (вместо шаблона главной страницы). После выбора шаблона вложенной главной страницы и нажатия кнопки "Добавить" откроется то же диалоговое окно "Выбор главной страницы", показанное на рис. 3.

Установите флажок

Рис. 02. Установите флажок "Выбор главной страницы", чтобы добавить вложенную главную страницу (щелкните, чтобы просмотреть изображение полного размера)

Привязка вложенной главной страницы к главной странице Simple.master

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

Декларативная разметка вложенной главной страницы, показанная ниже, содержит два элемента управления Content, ссылающиеся на два элемента управления ContentPlaceHolder верхнего уровня.

<%@ Master Language="C#" MasterPageFile="~/NestedMasterPages/Simple.master" AutoEventWireup="false" CodeFile="SimpleNested.master.cs" Inherits="NestedMasterPages_SimpleNested" %> 
 <asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server"> 
 </asp:Content> 
 <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server"> 
 </asp:Content>

<%@ Master %> За исключением директивы, начальная декларативная разметка вложенной главной страницы идентична разметке, которая изначально создается при привязке страницы содержимого к той же главной странице верхнего уровня. Как и директива страницы <%@ Page %> содержимого, <%@ Master %> директива здесь содержит MasterPageFile атрибут, указывающий родительскую главную страницу вложенной главной страницы. Основное различие между вложенной главной страницей и страницей содержимого, привязанной к той же главной странице верхнего уровня, заключается в том, что вложенные главные страницы могут включать элементы управления ContentPlaceHolder. Элементы управления ContentPlaceHolder вложенной главной странице определяют регионы, в которых страницы контента могут настраивать разметку.

Обновите эту вложенную главную страницу, чтобы она отображала текст "Hello, from SimpleNested!" в элементе управления "Содержимое", соответствующем элементу MainContent управления ContentPlaceHolder.

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server"> 
 <p>Hello, from SimpleNested!</p>
</asp:Content>

После добавления сохраните вложенную главную страницу и добавьте новую страницу содержимого в NestedMasterPages папку с именем Default.aspxи привязать ее к главной SimpleNested.master странице. После добавления этой страницы вы можете быть удивлены, чтобы увидеть, что он не содержит элементов управления содержимым (см. рис. 4)! Страница содержимого может получить доступ только к родительской главной странице ContentPlaceHolders. SimpleNested.master не содержит элементов управления ContentPlaceHolder; Таким образом, любая страница содержимого, привязанная к этой главной странице, не может содержать элементы управления содержимым.

Новая страница содержимого не содержит элементов управления содержимым

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

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

Обновите главную SimpleNested.master страницу, чтобы включить ContentPlaceHolder в два элемента управления Content. Присвойте элементу управления ContentPlaceHolder то же имя, что и элемент управления ContentPlaceHolder, на который ссылается элемент управления ContentHolder. То есть добавьте элемент управления ContentPlaceHolder с именем MainContent в элемент управления SimpleNested.master Content, который ссылается на MainContent ContentPlaceHolder в Simple.master. Выполните то же самое в элементе управления "Контент", который ссылается на head ContentPlaceHolder.

Примечание.

Хотя я рекомендую именовать элементы управления ContentPlaceHolder на вложенной главной странице так же, как ContentPlaceHolders на главной странице верхнего уровня, эта симметрия именования не требуется. Элементы управления ContentPlaceHolder можно указать на вложенной главной странице любое имя, которое вам нравится. Однако мне проще вспомнить, что ContentPlaceHolders соответствует регионам страницы, если эталонная страница верхнего уровня и вложенные главные страницы используют те же имена.

После добавления этих дополнений декларативная разметка главной SimpleNested.master страницы должна выглядеть примерно так:

<%@ Master Language="C#" MasterPageFile="~/NestedMasterPages/Simple.master"AutoEventWireup="false" CodeFile="SimpleNested.master.cs" Inherits="NestedMasterPages_SimpleNested" %> 
 <asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server"> 
 <asp:ContentPlaceHolder ID="head" runat="server"> 
 </asp:ContentPlaceHolder>
 </asp:Content> 
 <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server"> 
 <p>Hello, from SimpleNested!</p>
 <asp:ContentPlaceHolder ID="MainContent" runat="server"> 
 </asp:ContentPlaceHolder>
 </asp:Content>

Удалите только что созданную страницу содержимого Default.aspx и повторно добавьте ее, привязав ее к главной SimpleNested.master странице. На этот раз Visual Studio добавляет в приложение Default.aspxдва элемента управления ContentPlaceHolders, ссылающиеся на ContentPlaceHolders SimpleNested.master (см. рис. 6). Добавьте текст "Hello, from Default.aspx!" в элементе управления "Содержимое", на который ссылается MainContentссылка.

На рисунке 5 показаны три сущности, участвующие здесь , Simple.masterSimpleNested.masterи - и Default.aspx как они связаны друг с другом. Как показано на схеме, вложенная главная страница реализует элементы управления ContentPlaceHolder своего родительского элемента. Если эти регионы должны быть доступны для страницы содержимого, вложенные эталонные страницы должны добавить в элементы управления ContentPlaceHolders собственные элементы управления ContentPlaceHolders.

Верхний уровень и вложенные главные страницы определяют макет страницы содержимого

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

Это поведение иллюстрирует, как страница содержимого или эталонная страница только осознают ее родительскую главную страницу. Это поведение также указывается конструктором Visual Studio. На рисунке 6 показан конструктор для Default.aspx. Хотя конструктор четко показывает, какие регионы редактируются на странице содержимого и какие части не являются, он не отключает, какие регионы не редактируются из вложенной главной страницы и какие регионы находятся на главной странице верхнего уровня.

Страница содержимого теперь включает элементы управления содержимым для вложенных главных страниц ContentPlaceHolders

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

Шаг 3. Добавление второй простой вложенной главной страницы

Преимущество вложенных главных страниц более очевидно при наличии нескольких вложенных главных страниц. Чтобы проиллюстрировать это преимущество, создайте в папке NestedMasterPages другую вложенную главную страницу; присвойите ей имя новой вложенной главной страницы SimpleNestedAlternate.master и привязать ее к главной Simple.master странице. Добавьте элементы управления ContentPlaceHolder в два элемента управления "Содержимое" в вложенных главных страницах, как мы сделали на шаге 2. Кроме того, добавьте текст "Hello, from SimpleNestedAlternate!" в элементе управления "Контент", соответствующем главной странице MainContent верхнего уровня ContentPlaceHolder. После внесения этих изменений декларативная разметка новой вложенной главной страницы должна выглядеть следующим образом:

<%@ Master Language="C#" MasterPageFile="~/NestedMasterPages/Simple.master" AutoEventWireup="false" CodeFile="SimpleNestedAlternate.master.cs" Inherits="NestedMasterPages_SimpleNestedAlternate" %> 
 <asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
 <asp:ContentPlaceHolder ID="head" runat="server">
 </asp:ContentPlaceHolder> 
 </asp:Content> 
 <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server">
 <p>Hello, from SimpleNestedAlternate!</p> 
 <asp:ContentPlaceHolder ID="MainContent" runat="server">
 </asp:ContentPlaceHolder> 
 </asp:Content>

Создайте страницу содержимого с именем Alternate.aspx в папке NestedMasterPages и привязать ее к вложенной главной SimpleNestedAlternate.master странице. Добавьте текст "Hello, from Alternate!" в элементе управления "Содержимое", соответствующему MainContent. На рисунке 7 показано Alternate.aspx при просмотре с помощью конструктора Visual Studio.

Alternate.aspx привязан к главной странице SimpleNestedAlternate.master

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

Сравните конструктор на рис. 7 с конструктором на рис. 6. Обе страницы содержимого используют одинаковый макет, определенный на главной странице верхнего уровня (Simple.master), а именно название "Учебник по вложенным главным страницам (простой)". Тем не менее оба имеют различаемое содержимое, определенное на родительских главных страницах , текст "Hello, from SimpleNested!" на рис. 6 и "Hello, from SimpleNestedAlternate!" на рис. 7. Да, эти различия здесь тривиальные, но вы можете расширить этот пример, чтобы включить более значимые различия. Например, страница SimpleNested.master может включать меню с параметрами, относящимися к его страницам содержимого, в то время как SimpleNestedAlternate.master может иметь сведения, относящиеся к страницам содержимого, которые привязываются к нему.

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

Чтобы продемонстрировать простоту, с помощью которой можно изменить макет сайта, откройте Simple.master главную страницу и добавьте следующую разметку между элементами mainContent topContent <div>:

<div id="navContent"> 
 <asp:HyperLink ID="lnkDefault" runat="server" 
 NavigateUrl="~/NestedMasterPages/Default.aspx" 
 Text="Nested Master Page Example 1" /> 
 | 
 <asp:HyperLink ID="lnkAlternate" runat="server" 
 NavigateUrl="~/NestedMasterPages/Alternate.aspx" 
 Text="Nested Master Page Example 2" /> 
</div>

Это добавляет две ссылки на верхнюю часть каждой страницы, которая привязывается к Simple.master, SimpleNested.masterили SimpleNestedAlternate.master; эти изменения применяются ко всем вложенным главным страницам и их страницам содержимого немедленно. На рисунке 8 показано Alternate.aspx при просмотре через браузер. Обратите внимание на добавление ссылок в верхней части страницы (по сравнению с рис. 7).

Изменение на эталонную страницу верхнего уровня немедленно отражается на вложенных главных страницах и их страницах содержимого

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

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

На этом этапе мы рассмотрели преимущества вложенных главных страниц и видели, как создавать и использовать их в приложении ASP.NET. Однако примеры в шагах 1, 2 и 3 включали создание новой главной страницы верхнего уровня, новых вложенных главных страниц и новых страниц контента. Что делать с добавлением новой вложенной главной страницы на веб-сайт с существующей главной страницей верхнего уровня и страницами содержимого?

Интеграция вложенной главной страницы в существующий веб-сайт и связывание ее с существующими страницами контента требует немного больше усилий, чем начиная с нуля. Шаги 4, 5, 6 и 7 рассматривают эти проблемы по мере расширения демонстрационного приложения, чтобы включить новую вложенную главную страницу AdminNested.master , содержащую инструкции администратора и используемые страницами ASP.NET в папке ~/Admin .

Интеграция вложенной главной страницы в демонстрационное приложение представляет следующие препятствия:

  • Существующие страницы содержимого в папке ~/Admin имеют определенные ожидания от главной страницы. Для начала они ожидают, что некоторые элементы управления ContentPlaceHolder будут присутствовать. Кроме того, страницы ~/Admin/AddProduct.aspx ~/Admin/Products.aspx вызывают открытый RefreshRecentProductsGrid метод главной страницы, задают его GridMessageText свойство или имеют обработчик событий для его PricesDoubled события. Следовательно, вложенная главная страница должна предоставлять одинаковые элементы ContentPlaceHolders и общедоступных участников.
  • В предыдущем руководстве мы улучшили класс для BasePage динамического задания Page свойства объекта MasterPageFile на основе переменной сеанса. Как поддерживать динамические главные страницы при использовании вложенных главных страниц?

Эти две проблемы будут возникать, так как мы создадим вложенную главную страницу и используем ее на наших существующих страницах содержимого. Мы расследуем и удалим эти проблемы по мере их возникновения.

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

Наша первая задача — создать вложенную главную страницу, которая будет использоваться страницами в разделе администрирования. Как мы видели на шаге 2, при добавлении новой вложенной главной страницы необходимо указать родительскую главную страницу вложенной главной страницы. Но у нас есть две главные страницы верхнего уровня: Site.master и Alternate.master. Помните, что мы создали в предыдущем руководстве и написали код в BasePage классе, который задает свойство объекта MasterPageFile Page во время выполнения Site.master Alternate.master или в зависимости от значения переменной сеансаMyMasterPage.Alternate.master

Как настроить вложенную главную страницу таким образом, чтобы она использовала соответствующую главную страницу верхнего уровня? Это можно сделать двумя способами.

  • Создайте две вложенные главные страницы и AdminNestedSite.master AdminNestedAlternate.masterпривязать их к главным страницам Site.master верхнего уровня и Alternate.masterсоответственно. Затем BasePageмы задали Page объекту MasterPageFile соответствующую вложенную главную страницу.
  • Создайте одну вложенную главную страницу и используйте эту главную страницу. Затем во время выполнения необходимо задать для свойства вложенной главной страницы MasterPageFile соответствующую главную страницу верхнего уровня во время выполнения. (Как вы могли бы понять, к настоящему моменту главные страницы также имеют MasterPageFile свойство.)

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

Добавьте вложенную главную страницу в папку ~/Admin.

Рис. 09. Добавление в папку вложенной главной ~/Admin страницы. (Щелкните, чтобы просмотреть изображение полного размера)

Так как вложенная главная страница привязана к главной странице с четырьмя элементами управления ContentPlaceHolder, Visual Studio добавляет четыре элемента управления Content в новый вложенный главный файл разметки. Как и в шагах 2 и 3, добавьте элемент управления ContentPlaceHolder в каждом элементе управления ContentPlace, предоставляя ему то же имя, что и элемент управления ContentPlaceHolder верхнего уровня. Кроме того, добавьте следующую разметку в элемент управления Content, соответствующий MainContent ContentPlaceHolder:

<div class="instructions"> 
 <b>Administration Instructions:</b>
 <br /> 
 The pages in the Administration section allow you, the Administrator, to 
 add new products and view existing products. 
</div>

Затем определите instructions класс CSS в файлах Styles.css CSS и AlternateStyles.css CSS. Следующие правила CSS приводят к отображению html-элементов с instructions цветом светло-желтого фона и черной сплошной границы:

.instructions 
{ 
 padding: 6px; 
 border: dashed 1px black; 
 background-color: #ffb; 
 margin-bottom: 10px; 
}

Так как эта разметка была добавлена на вложенную главную страницу, она будет отображаться только на тех страницах, которые используют эту вложенную главную страницу (а именно страницы в разделе администрирования).

После добавления этих дополнений к вложенной главной странице его декларативная разметка должна выглядеть следующим образом:

<%@ Master Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="false" CodeFile="AdminNested.master.cs" Inherits="Admin_AdminNested" %> 
 <asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server"> 
 <asp:ContentPlaceHolder ID="head" runat="server"> 
 </asp:ContentPlaceHolder>
 </asp:Content> 
 <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server"> 
 <div class="instructions">
 <b>Administration Instructions:</b>
 <br /> 
 The pages in the Administration section allow you, the Administrator, to 
 add new products and view existing products. 
 </div> 
 <asp:ContentPlaceHolder ID="MainContent" runat="server"> 
 </asp:ContentPlaceHolder>
 </asp:Content> 
 <asp:Content ID="Content3" ContentPlaceHolderID="QuickLoginUI" Runat="Server"> 
 <asp:ContentPlaceHolder ID="QuickLoginUI" runat="server"> 
 </asp:ContentPlaceHolder>
 </asp:Content> 
 <asp:Content ID="Content4" ContentPlaceHolderID="LeftColumnContent" Runat="Server"> 
 <asp:ContentPlaceHolder ID="LeftColumnContent" runat="server"> 
 </asp:ContentPlaceHolder>
 </asp:Content>

Обратите внимание, что каждый элемент управления ContentPlaceHolder имеет элемент управления ContentPlaceHolder и свойства элементов управления ID ContentPlaceHolder назначаются тем же значениям, что и соответствующие элементы управления ContentPlaceHolder на главной странице верхнего уровня. Кроме того, разметка раздела администрирования отображается в MainContent ContentPlaceHolder.

На рисунке 10 показана AdminNested.master вложенная главная страница при просмотре с помощью конструктора Visual Studio. Инструкции можно просмотреть в желтом поле в верхней части MainContent элемента управления "Содержимое".

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

Рис. 10. Вложенная главная страница расширяет эталонную страницу верхнего уровня, чтобы включить инструкции администратора. (Щелкните, чтобы просмотреть изображение полного размера)

Шаг 5. Обновление существующих страниц контента для использования новой вложенной главной страницы

В любой момент, когда мы добавим новую страницу содержимого в раздел администрирования, необходимо привязать ее к главной AdminNested.master странице, которую мы только что создали. Но как насчет существующих страниц содержимого? В настоящее время все страницы контента на сайте являются производными от BasePage класса, который программно задает главную страницу страницы контента во время выполнения. Это не поведение, которое мы хотим использовать для страниц содержимого в разделе администрирования. Вместо этого мы хотим, чтобы эти страницы содержимого всегда использовали страницу AdminNested.master . Она будет отвечать за вложенную главную страницу, чтобы выбрать правильную страницу содержимого верхнего уровня во время выполнения.

Для достижения этого желаемого поведения рекомендуется создать новый пользовательский базовый класс страницы с именем AdminBasePage , расширяющим BasePage класс. AdminBasePage затем можно переопределить SetMasterPageFile и задать Page для объекта MasterPageFile жестко закодированное значение "~/Admin/AdminNested.master". Таким образом, любая страница, наследуемая от нее, в то время как любая страница, наследуемая от AdminBasePage BasePage нееMasterPageFile, динамически задана как "~/Site.master", так и "~/Alternate.master" на основе значения переменной сеансаMyMasterPage.AdminNested.master

Начните с добавления нового файла класса в папку App_Code с именем AdminBasePage.cs. Расширьте AdminBasePage BasePage и переопределите SetMasterPageFile метод. В этом методе MasterPageFile назначьте значение ~/Admin/AdminNested.master. После внесения этих изменений файл класса должен выглядеть следующим образом:

public class AdminBasePage : BasePage 
{ 
    protected override void SetMasterPageFile() 
    { 
        this.MasterPageFile = "~/Admin/AdminNested.master"; 
    } 
}

Теперь необходимо иметь существующие страницы содержимого в разделе администрирования, производные AdminBasePage от нее BasePage. Перейдите к файлу класса code-behind для каждой страницы содержимого в папке ~/Admin и внесите это изменение. Например, в ~/Admin/Default.aspx объявлении класса code-behind изменится:

public partial class Admin_Default : BasePage

Кому:

public partial class Admin_Default : AdminBasePage

На рисунке 11 показано, как эталонная страница верхнего уровня (Site.master или Alternate.master), вложенные главные страницы (AdminNested.master) и страницы содержимого раздела администрирования связаны друг с другом.

Вложенная главная страница определяет содержимое, относяемое к страницам в разделе администрирования

Рис. 11. Вложенная главная страница определяет содержимое для страниц в разделе администрирования (щелкните, чтобы просмотреть изображение полного размера)

Шаг 6. Зеркальное отображение общедоступных методов и свойств главной страницы

Помните, что ~/Admin/AddProduct.aspx страницы ~/Admin/Products.aspx взаимодействуют программно с главной страницей: ~/Admin/AddProduct.aspx вызывает открытый RefreshRecentProductsGrid метод главной страницы и задает его GridMessageText свойство; ~/Admin/Products.aspx имеет обработчик событий для PricesDoubled события. В предыдущем руководстве мы создали абстрактный BaseMasterPage класс, определяющий эти открытые члены.

~/Admin/Products.aspx Предполагается~/Admin/AddProduct.aspx, что главная страница является производным от BaseMasterPage класса. Однако страница AdminNested.master в настоящее время расширяет System.Web.UI.MasterPage класс. В результате при посещении ~/Admin/Products.aspx InvalidCastException создается сообщение:"Не удается привести объект типа "ASP.admin_adminnested_master", чтобы ввести "BaseMasterPage".

Чтобы устранить эту проблему, необходимо расширить AdminNested.master класс BaseMasterPagecode-behind. Обновите объявление класса кода вложенной главной странице из:

public partial class Admin_AdminNested : System.Web.UI.MasterPage

Кому:

public partial class Admin_AdminNested : BaseMasterPage

Мы еще не сделали. BaseMasterPage Так как класс является абстрактным, необходимо переопределить abstract члены RefreshRecentProductsGrid и GridMessageText. Эти элементы используются главными страницами верхнего уровня для обновления пользовательских интерфейсов. (На самом деле, только эталонная Site.master страница использует эти методы, хотя оба главных страниц верхнего уровня реализуют эти методы, так как оба расширения BaseMasterPage.)

Хотя нам нужно реализовать эти члены, AdminNested.masterвсе эти реализации необходимо сделать, это просто вызвать один и тот же член на главной странице верхнего уровня, используемой вложенной главной страницей. Например, когда страница содержимого в разделе администрирования вызывает метод вложенной главной страницыRefreshRecentProductsGrid, все вложенные главные страницы должны выполняться, в свою очередь, вызов Site.master или Alternate.masterRefreshRecentProductsGrid метод.

Для этого сначала добавьте следующую @MasterType директиву в начало AdminNested.master:

<%@ MasterType TypeName="BaseMasterPage" %>

Помните, что директива @MasterType добавляет строго типизированное свойство в класс code-behind с именем Master. Затем переопределите элементы и члены и GridMessageText просто делегировать RefreshRecentProductsGrid вызов Masterсоответствующему методу:

public partial class Admin_AdminNested : BaseMasterPage 
{ 
    public override void RefreshRecentProductsGrid() 
    { 
        Master.RefreshRecentProductsGrid();
    } 
    public override string GridMessageText
    { 
        get 
        {
            return Master.GridMessageText;
        } 
        set
        { 
            Master.GridMessageText = value; 
        } 
    }
}

В этом коде вы сможете посетить и использовать страницы содержимого в разделе администрирования. На рисунке 12 показана ~/Admin/Products.aspx страница при просмотре через браузер. Как видно, на странице содержится поле "Инструкции администрирования", которое определено на вложенной главной странице.

Страницы содержимого в разделе администрирования содержат инструкции в верхней части каждой страницы

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

Шаг 7. Использование соответствующей главной страницы верхнего уровня во время выполнения

Хотя все страницы содержимого в разделе администрирования полностью функциональны, они используют одну и ту же главную страницу верхнего уровня и игнорируют главную страницу, выбранную пользователем ChooseMasterPage.aspx. Это происходит из-за того, что вложенная главная страница имеет его MasterPageFile свойство статически задано Site.master в директиве <%@ Master %> .

Чтобы использовать главную страницу верхнего уровня, выбранную конечным пользователем, необходимо задать AdminNested.masterMasterPageFile для свойства значение в переменной MyMasterPage сеанса. Так как мы устанавливаем свойства страниц содержимого в BasePage, возможно, мы задали свойство вложенной главной страницы MasterPageFile MasterPageFile или в BaseMasterPage AdminNested.masterклассе кода программной части. Однако это не будет работать, так как нам нужно задать MasterPageFile свойство к концу этапа PreInit. Самое раннее время, которое мы можем программным способом подключиться к жизненному циклу страницы с главной страницы, — это этап Init (который происходит после этапа PreInit).

Поэтому необходимо задать свойство вложенной главной страницы MasterPageFile на страницах содержимого. Единственные страницы содержимого, использующие эталонную AdminNested.master страницу, производные от AdminBasePage. Поэтому мы можем поместить эту логику туда. На шаге 5 мы перекроем SetMasterPageFile метод, установив Page для свойства объекта MasterPageFile значение ~/Admin/AdminNested.master. Обновите, SetMasterPageFile чтобы также задать свойство главной страницы MasterPageFile результатом, хранящимся в сеансе:

public class AdminBasePage : BasePage 
{ 
    protected override void SetMasterPageFile() 
    { 
        this.MasterPageFile = "~/Admin/AdminNested.master"; 
        Page.Master.MasterPageFile = base.GetMasterPageFileFromSession(); 
    } 
}

Метод GetMasterPageFileFromSession , который мы добавили в BasePage класс в предыдущем руководстве, возвращает соответствующий путь к файлу главной страницы на основе значения переменной сеанса.

В этом случае выбор главной страницы пользователя переместит в раздел администрирования. На рисунке 13 показана та же страница, что и на рис. 12, но после изменения выбора Alternate.masterглавной страницы пользователя.

Страница вложенного администрирования использует главную страницу верхнего уровня, выбранную пользователем

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

Итоги

Подобно тому, как страницы содержимого могут привязаться к главной странице, можно создать вложенные главные страницы, привязав дочерние эталонные страницы к родительской главной странице. На дочерней главной странице могут быть определены элементы управления содержимым для каждого родительского элемента ContentPlaceHolders; Затем он может добавить собственные элементы управления ContentPlaceHolder (а также другие разметки) в эти элементы управления Content. Вложенные эталонные страницы очень полезны в крупных веб-приложениях, где все страницы совместно используют внешний вид и ощущение, но для некоторых разделов сайта требуются уникальные настройки.

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

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

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

Об авторе

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

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

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