Средства форматирования страниц
Создание страниц содержимого для мастер-страницы
Мы для нашего примера создадим 4 страницы содержимого с простыми именами:
- Satellites.aspx - первая страница, главная, не будет иметь свое содержимое, значит вся мастер страница проявится на выходе. Остальные три страницы будут переопределять все шаблоны мастер-страницы, кроме первого - колонтитула
- Satellite1.aspx - будет вызываться по первой ссылке в разделе "Наши филиалы" и переопределять содержимое всех контейнеров, кроме верхнего колонтитула
- Satellite2.aspx - будет вызываться по второй ссылке в разделе "Наши филиалы"
- Satellite3.aspx - будет вызываться по третьей ссылке в разделе "Наши филиалы"
Есть несколько способов создания мастер-страниц с помощью оболочки. Попробуем их.
Первый способ
- В панели Solution Explorer выделите корень Web-дерева и выполните команду меню Website/Add New Item (или команду Add New Item контекстного меню)
- В появившемся диалоговом окне отметьте показанные настройки, включая Select master page
- В следующем окне выберите мастер-страницу
Созданная страница добавится в корень Web-дерева и будет содержать контейнеры с подключенным пустым содержимым для всех шаблонов выбранной мастер-страницы.
Второй способ
- В панели Solution Explorer выделите нужную мастер-страницу и выполните команду меню Website/Add Content Page (или команду Add Content Page контекстного меню)
Будет создана страница содержимого, размещенная в том же каталоге, что и выделенная мастер-страница, но добавленный атрибут MasterPageFile будет прописан относительно корня Web-дерева, например,
MasterPageFile="~/MasterPages/Title.master" - (как-бы абсолютный адрес в пределах сайта)
Это значит, что мы можем переместить страницу содержимого в любую папку в пределах Web-дерева, и везде адрес мастер-страницы буден известен системе ASP.NET. Но если мы изменили местоположение мастер-страницы, то оболочка автоматически не исправит ее адрес в использующих страницах содержимого, это нужно делать вручную. Поэтому, перемещайте мастер-страницу по Web-дереву куда хотите, но до тех пор, пока не начали создавать для нее страницы содержимого. Иначе потом придется долго искать ошибки.
Третий способ
- Откройте мастер-страницу на редактирование и щелкните на ней в любом месте правой кнопкой мыши. Появится контекстное меню с уже известной нам командой Add Content Page
Обратите внимание, что двумя последними способами страница создается без отдельного файла поддержки C#. Это легко исправить, добавив к проекту файл .cs с предшествующим именем страницы. Правда, оболочка при этом спросит, создавать ли для этого класса отдельную папку со стандартным именем App_Code, на что нужно ответить Нет. И еще, при таком способе добавления к странице файла поддержки нужно вручную прописать необходимые атрибуты в декларации @Page
AutoEventWireup="true" CodeFile="XXX.aspx.cs" Inherits="YYY"
Вернемся к нашему примеру. Мы не собираемся программно управлять нашими страницами при иллюстрации рассматриваемой темы мастер-страниц. Нам, главное, убедиться, что все, о чем мы так долго болтали, работает! Поэтому, создадим страницы со встроенным кодом поддержки (пустым, естественно).
- Щелкните правой кнопкой мыши на открытой мастер-странице ~/MasterPages/Title.master в любом месте и командой Add Content Page создайте страницу содержимого Default.aspx
- Переименуйте страницу Default.aspx в Satellite.aspx и переместите ее в корневую папку Web-дерева
- Подобным же образом создайте и переместите в корень остальные страницы содержимого: Satellite1.aspx, Satellite2.aspx, Satellite3.aspx. Но можно просто раскопировать в корне в трех экземплярах файл Satellite.aspx, учитывая, что все страницы будут ссылаться на одну и туже мастер-страницу
Теперь давайте корректировать заготовки страниц содержимого. Но прежде всего нужно доделать нашу мастер-страницу, определив ссылки в левой ячейке таблицы на только что созданные страницы содержимого.
- Выполните команду Window/Close All Documents, чтобы закрыть все редактируемые на текущий момент файлы
- В панели Solution Explorer щелкните правой кнопкой мыши на файле ~/MasterPages/Title.master и выполните команду View Designer, чтобы открыть мастер-страницу сразу в режиме Design
- Поочередно выделяя элементы гиперссылок, установите их свойство NavigateUrl на соответствующие страницы содержимого Satellite1.aspx, Satellite2.aspx, Satellite3.aspx. Сохраните и закройте мастер-страницу Title.master
Отредактируем страницы содержимого, начнем с Satellite.aspx
- В панели Solution Explorer назначьте страницу Satellite.aspx стартовой и откройте ее на редактирование в режиме Design
Что мы видим на данном этапе времени проектирования:
- Мы видим просвечивающуюся сквозь страницу_содержимого мастер-страницу (шаблон). Причем заполнители (элементы вне контейнеров-шаблонов) мастер-страницы просвечиваются тускло. Это говорит о том, что их редактирование недоступно из страницы содержимого, но они полностью отобразятся и будут доступны на этапе выполнения
- Места, где на мастер-странице расположены контейнеры-шаблоны, показаны ярко, но закрыты пустыми (пока) контейнерами содержимого. Причем закрыто только содержимое шаблонов мастер-страницы, а фон полность просвечивается.
- Удалите все контейнеры содержимого из страницы Satellite.aspx, оставьте только строку с директивой @Page. Эта страница у нас будет стартовой и своего содержимого иметь не будет
- Перейдите на странице Satellite.aspx в режим Design и мы видим, что проявилось и содержимое шаблонов мастер-страницы. Оно и будет отображаться при выполнении во всех местах, где нет своих прикрепленных контейнеров на странице содержимого
- Исполните страницу Satellite.aspx, получится ожидаемый результат
- Пощелкайте по ссылкам и обратите внимание, как меняется адрес в броузере (ссылки работают). На адресуемых страницах мы пока не убрали и не изменили контейнеры содержимого, поэтому там на месте контейнеров шаблона ничего не будет (пустое содержимое контейнеров место при исполнении не занимает). Умная технология Большого Билла!
Теперь нужно наполнить страницы ссылок индивидуальным содержимым.
Приведем окончательный вариант дескрипторного кода для всех страниц данного примера
Мастер-страница Title.master
<%@ Master Language="C#" %> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div style="text-align: center"> <asp:Image ID="ImageBanner" runat="server" ImageUrl="~/MasterPages/Banner.png" /> <h1 style="color: Green"> Мы приветствуем Вас на нашем сайте!!! </h1> <br /> <table border="0" width="100%"> <tr> <td colspan="2"> <asp:Panel ID="Panel1" runat="server" Height="100%" Width="100%" BackImageUrl="~/MasterPages/BackTitle.jpg"> <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server"> <div style="font-weight: bold; font-size: xx-large; color: red; text-align: center"> Сведения об автошколе в целом </div> </asp:ContentPlaceHolder> </asp:Panel> </td> </tr> <tr> <td style="width: 25%; background-color: #9DFF7E" valign="top"> <strong style="color: Blue">Наши филиалы:</strong><br /> <br /> <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="~/Satellite1.aspx">Ленинский район</asp:HyperLink><br /> <br /> <asp:HyperLink ID="HyperLink2" runat="server" NavigateUrl="~/Satellite2.aspx">Центральный район</asp:HyperLink><br /> <br /> <asp:HyperLink ID="HyperLink3" runat="server" NavigateUrl="~/Satellite3.aspx">Свердловский район</asp:HyperLink> </td> <td style="background-color: #FFB8FF"> <asp:ContentPlaceHolder ID="ContentPlaceHolder2" runat="server"> Вот уже более 12 лет мы занимаемся подготовкой водителей категории "B" в г.Красноярске и всегда занимали первые места в сводках МРЭО ГИБДД по качеству обучения. Автошкола всегда нацелена на успех наших клиентов в сдаче экзаменов ГАИ с первого раза и своевременном получении водительского удостоверения. <br /> <br /> Мы обеспечиваем максимальные удобства своим клиентам. Для этого существуют вечерняя, воскресная и заочная формы обучения. Наши курсанты имеют возможность бесплатно и неограниченно пользоваться компьютерным классом. Учебные автомобили прибывают по заявке клиента к назначенному им месту. Развивается сеть филиалов автошколы в г.Красноярске. </asp:ContentPlaceHolder> </td> </tr> <tr style="background-color: #FFFF92"> <td colspan="2"> <asp:ContentPlaceHolder ID="ContentPlaceHolder3" runat="server"> <strong>Автошкола Диалог-Сервис в целом работает без перерыва на обед и выходных с 8 часов утра до 9 часов вечера!!! </strong> </asp:ContentPlaceHolder> </td> </tr> </table> <p style="text-align: right; color: Blue; font-family: 'Courier New'; font: bold italic"> <img id="IMG1" runat="server" src="LIGHT.ICO" /> &nbsp;Copyright © 2007</p> <asp:ContentPlaceHolder ID="ContentPlaceHolder4" runat="server"> <strong><em>Вы уж, пожалуйста, наведывайтесь к нам почаще!</em></strong> </asp:ContentPlaceHolder> </div> </form> </body> </html>
Запускающая страница содержимого Satellite.aspx
Все контейнеры <asp:Content> уничтожены, поэтому страница используется только как запускающая и не добавляет к мастер-странице своего содержимого.
<%@ Page Language="C#" MasterPageFile="~/MasterPages/Title.master" Title="Untitled Page" %>
Страница содержимого Satellite1.aspx
Страница имеет все контейнеры переопределяющего содержимого, поэтому от мастер-страницы проявляются только заполнители.
<%@ Page Language="C#" MasterPageFile="~/MasterPages/Title.master" Title="Untitled Page" %> <asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server"> <div style="font-weight: bold; font-size: xx-large; color: red; text-align: center"> Сведения о филиале в Ленинском районе </div> </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder2" Runat="Server"> Филиал в Ленинском районе такой хороший!<br /> ..........................<br /> и т.д. </asp:Content> <asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder3" Runat="Server"> <strong>Филиал в Ленинском районе работает без перерыва на обед и выходных с 8 часов утра до 9 часов вечера!!! </strong> </asp:Content> <asp:Content ID="Content4" ContentPlaceHolderID="ContentPlaceHolder4" Runat="Server"> <strong><em>Вы уж, пожалуйста, наведывайтесь к нам почаще в филиал Ленинского района!</em></strong> </asp:Content>
Страница содержимого Satellite2.aspx
Страница имеет все контейнеры переопределяющего содержимого, поэтому от мастер-страницы проявляются только заполнители.
<%@ Page Language="C#" MasterPageFile="~/MasterPages/Title.master" Title="Untitled Page" %> <asp:Content ID="Content1" runat="Server" ContentPlaceHolderID="ContentPlaceHolder1"> <div style="font-weight: bold; font-size: xx-large; color: red; text-align: center"> Сведения о филиале в Центральном районе </div> </asp:Content> <asp:Content ID="Content2" runat="Server" ContentPlaceHolderID="ContentPlaceHolder2"> Филиал в Центральном районе такой хороший!<br /> ..........................<br /> и т.д. </asp:Content> <asp:Content ID="Content3" runat="Server" ContentPlaceHolderID="ContentPlaceHolder3"> <strong> Филиал в Центральном районе работает с перерывом на обед и с выходными!!! </strong> </asp:Content> <asp:Content ID="Content4" runat="Server" ContentPlaceHolderID="ContentPlaceHolder4"> <strong><em>Вы уж, пожалуйста, наведывайтесь к нам почаще в филиал Центрального района!</em> </strong> </asp:Content>
Страница содержимого Satellite3.aspx
Третий контейнер страницы содержимого отсутствует, поэтому на его месте проявится содержимое третьего шаблона мастер-страницы. Четвертый контейнер содержимого существует, но пустой, поэтому на его месте ничего не проявится.
<%@ Page Language="C#" MasterPageFile="~/MasterPages/Title.master" Title="Untitled Page" %> <asp:Content ID="Content1" runat="Server" ContentPlaceHolderID="ContentPlaceHolder1"> <div style="font-weight: bold; font-size: xx-large; color: red; text-align: center"> Сведения о филиале в Свердловком районе </div> </asp:Content> <asp:Content ID="Content2" runat="Server" ContentPlaceHolderID="ContentPlaceHolder2"> Филиал в Свердловском районе такой хороший!<br /> ..........................<br /> и т.д. </asp:Content> <asp:Content ID="Content4" runat="Server" ContentPlaceHolderID="ContentPlaceHolder4"> </asp:Content>
Программное управление мастер-страницей из страницы содержимого
В странице содержимого мы можем менять только содержимое контейнеров <asp:Content>, а содержимое заполнителей мастер-страницы и ее заголовок являются недоступными на этапе проектирования. Но иногда, не трогая спроектированную мастер-страницу, нужно в ее заполнителях что-то изменить из конкретной страницы содержимого. Это можно сделать программно на этапе выполнения. При этом нужно учитывать порядок срабатывания событий при загрузке страницы:
- Вначале ASP.NET создает элементы управления мастер-страницы, а потом дочерние элементы на странице содержимого
- Затем генерируется событие Page.Init мастер-страницы, вслед за которым возбуждается событие Page.Init страницы содержимого
- Затем срабатывает событие Page.Load мастер-страницы, а за ним то же событие страницы содержимого
Такой порядок означает, что если мы программно меняем одни и те же настройки в мастер-странице и в странице содержимого, то последними останутся изменения, выполненные в коде страницы содержимого.
Управление заголовком
Мастер-страница имеет заголовок <head>...</head> обычной страницы, где можно задавать все составляющие его дескрипторы и это появится на результирующей странице. Но иногда на странице содержимого нужно определить свои дескрипторы заголовка. Декларативно (на этапе проектирования) в странице содержимого можно переоперелить только дескриптор <title>, добавив в директиву @Page атрибут Title="..." страницы содержимого. В этом случае дескриптор <head> мастер-страницы должен обязательно быть серверным (что и делает по умолчанию мастер заготовок оболочки).
Программно можно переопределять не только дескриптор <title>, но и другие дескрипторы заголовка. И опять, дескриптор <head> мастер-страницы должен обязательно быть серверным. Для программного управления элементами заголовка <head> мастер-страницы из текущей страницы содержимого нужно в странице содержимого получить ссылку на объект Page мастер-страницы. Это делается через свойство Page.Master объекта текущей страницы содержимого, у которого, в свою очередь, свойство Master.Page и определяет ссылку на объект Page мастер-страницы.
Ниже приведены равноценные коды получения ссылки на объект Page мастер-страницы из страницы содержимого
Page masterPage = base.Master.Page; Page masterPage = this.Master.Page; Page masterPage = Master.Page;
Ключевые слова base или this не являются обязательными. Они напоминают, что Master является свойством объекта текущей страницы.
Декларативное переопределение <title>
-
Создайте копию страницы Satellite.aspx, назначьте ей имя SatelliteExt.aspx и сделайте стартовой
Попробуем на странице SatelliteExt.aspx переопределить дескриптор <title> мастер-страницы. Текущий код страницы такой
<%@ Page Language="C#" MasterPageFile="~/MasterPages/Title.master" Title="Untitled Page" %>
-
Замените атрибут Title директивы @Page на следующий
<%@ Page Language="C#" MasterPageFile="~/MasterPages/Title.master" Title="Декларативный заголовок SatelliteExt.aspx" %>
- Исполните страницу - результат будет таким
Программное переопределение <title>
Поскольку мы не создавали для страницы SatelliteExt.aspx отдельный файл кода поддержки, то код переопределения заголовка будем писать в скриптах страницы
-
Переведите страницу SatelliteExt.aspx в режим Design и щелкните дважды на притушенной области проступающего заполнителя мастер-страницы
Оболочка автоматически создаст блок скрипта и вставит в него заготовку обработчика события Page.Load.
-
Заполните обработчик так
<%@ Page Language="C#" MasterPageFile="~/MasterPages/Title.master" Title="Декларативный заголовок SatelliteExt.aspx" %> <script runat="server"> protected void Page_Load(object sender, EventArgs e) { // Получаем ссылку на мастер-страницу Page masterPage = Master.Page; // Переопределяем строку заголовка masterPage.Header.Title = "Программный заголовок SatelliteExt.aspx"; } </script>
- Исполните страницу - результат будет таким
Несмотря на то, что мы оставили декларативный атрибут Title, обработчик переопределил его в окончательном выводе. Это и понятно: декларативный атрибут инициируется при создании объекта заголовка, а обработчик Page_Load() срабатывает позднее.