Вложенные эталонные страницы (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
. Мы будем использовать вложенные главные страницы с двумя (или более) эталонными страницами, начиная с раздела "Использование вложенной главной страницы для раздела администрирования" далее в этом руководстве.
Представьте, что нам было предложено настроить макет страниц администрирования, чтобы включить дополнительные сведения или ссылки, которые в противном случае не будут присутствовать на других страницах на сайте. Существует четыре способа реализации этого требования:
- Вручную добавьте сведения об администрирования и ссылки на каждую страницу содержимого в папке
~/Admin
. Site.master
Обновите эталонную страницу, чтобы включить сведения и ссылки для раздела администрирования, а затем добавьте код на главную страницу, чтобы отобразить или скрыть эти разделы на основе того, просматривается ли одна из страниц администрирования.- Создайте главную страницу специально для раздела администрирования, скопируйте разметку из
Site.master
, добавьте сведения и ссылки для раздела администрирования, а затем обновите страницы содержимого в папке~/Admin
, чтобы использовать эту новую эталонную страницу. - Создайте вложенную главную страницу, которая привязывается
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.
Рис. 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. Установите флажок "Выбор главной страницы", чтобы добавить вложенную главную страницу (щелкните, чтобы просмотреть изображение полного размера)
Рис. 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.master
SimpleNested.master
и - и Default.aspx
как они связаны друг с другом. Как показано на схеме, вложенная главная страница реализует элементы управления ContentPlaceHolder своего родительского элемента. Если эти регионы должны быть доступны для страницы содержимого, вложенные эталонные страницы должны добавить в элементы управления ContentPlaceHolders собственные элементы управления ContentPlaceHolders.
Рис. 05. Верхний уровень и вложенные главные страницы определяют макет страницы содержимого (щелкните, чтобы просмотреть изображение полного размера)
Это поведение иллюстрирует, как страница содержимого или эталонная страница только осознают ее родительскую главную страницу. Это поведение также указывается конструктором Visual Studio. На рисунке 6 показан конструктор для Default.aspx
. Хотя конструктор четко показывает, какие регионы редактируются на странице содержимого и какие части не являются, он не отключает, какие регионы не редактируются из вложенной главной страницы и какие регионы находятся на главной странице верхнего уровня.
Рис. 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.
Рис. 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
ради согласованности.
Рис. 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
класс BaseMasterPage
code-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.master
RefreshRecentProductsGrid
метод.
Для этого сначала добавьте следующую @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.master
MasterPageFile
для свойства значение в переменной 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.NET главные страницы
- Советы по вложенным главным страницам и времени разработки VS 2005
- Поддержка вложенной главной страницы VS 2008
Об авторе
Скотт Митчелл, автор нескольких книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с технологиями Microsoft Web с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга Сэмс Учит себя ASP.NET 3,5 в 24 часах. Скотт можно получить по mitchell@4GuysFromRolla.com адресу или через свой блог.http://ScottOnWriting.NET
Особое спасибо
Эта серия учебников была проверена многими полезными рецензентами. Хотите просмотреть мои предстоящие статьи MSDN? Если да, выбросить меня линию в mitchell@4GuysFromRolla.com