LAV_ СИТспец_маг2014-15 / Модуль1_2013-14 / Web-приложения ASP_NET
.doc
Рассматриваются принципы использования мастер-страниц при разработке Интернет-приложений. Приводятся примеры построения типовых мастер-страниц и страниц содержимого. Рассматриваются возможности организации переключения между различными мастер-страницами и программного обращения к содержимому мастер-страниц из страниц содержимого. Приводятся примеры использования вложенных мастер-страниц. |
Цель лекции: изучить принципы использования мастер-страниц при построении интернет-приложения, рассмотреть возможности применения вложенных мастер-страниц, а также организации программного взаимодействия страницы содержимого с мастер-страницей. Создаваемые Web-страницы сегодня очень редко разрабатываются "с нуля". Обычно при создании таких страниц используются уже готовые шаблоны, либо таковые создаются в процессе разработки Web-страниц приложения. Это связано с тем, что страницы Web-приложения составляют некое единое целое, объединенное едиными требованиями к оформлению, содержанию, расположению элементов управления и т. д. Таким образом, пользователь попадает в некую среду, которая должна быть максимально удобна для удовлетворения всех потребностей пользователя. Одним из средств решения подобных задач являются мастер-страницы (master pages). Они реализуют простую модель создания шаблонов форм с возможностью их повторного использования. Для реализации данного механизма в ASP.NET введены такие типы страниц, как мастер-страницы (master pages) и страницы содержимого (content pages). Мастер-страница представляет собой шаблон страницы, при этом она может содержать любые элементы, допустимые для обычной страницы, а также программный код. Страница содержимого включает в себя допустимые элементы управления и с помощью их определяет содержимое, которым заполняются специальные области мастер страниц. Каждая страница содержимого ссылается на одну мастер-страницу от которой получает элементы и их расположение. Обычно мастер-страница содержит фиксированные элементы, одинаковые для всех страниц, и заполнитель содержимого для остальной части страницы. Наиболее типичными фиксированными элементами являются верхний и нижний колонтитулы, панель навигации, панель меню и т.д. Страница содержимого получает от мастер-страницы фиксированные элементы и предоставляет дополнительное содержимое. Для демонстрации возможностей мастер-страниц рассмотрим пример создания простой мастер-страницы и страницы содержимого. Схематично структура мастер-страницы показана на рис. 6.1.
Рис. 6.1. Типовая структура мастер-страницы Такая структура характерна для очень большого числа Web-сайтов. Изображенные на рис. 6.1 верхний колонтитул, нижний колонтитул и панель навигации являются общими для всех страниц элементами, содержимое которых постоянно и не меняется. Содержимое страницы - та ее часть, которая меняется в зависимости от действий пользователя, именно в ней отображается полезная для пользователя информация и именно здесь будет размещаться область, в которой будет отображаться страница содержимого. Создадим новый сайт с помощью Visual Studio. Как и всегда, по умолчанию он состоит из пустой страницы Default.aspx. Сейчас необходимо добавить к данному Web-приложению мастер-страницу. Для этого необходимо выполнить команду главного меню Website Add New Item и в открывшемся окне выбрать пункт Master Page, как показано на рис. 6.2.
Рис. 6.2. Окно добавления мастер-страницы к текущему Web-приложению При этом создается новая мастер-страница с именем MainMasterPage.master. Как видно из ее исходного кода, она подобна обычной Web-странице ASP.NET Отличие заключается в том, что Web-страницы начинаются с директивы Page, а мастер-страница - с директивы Master. <%@ Master Language="C#" AutoEventWireup="true" CodeFile= "MainMasterPage.master.cs" Inherits="MainMasterPage" %> Еще одним важным отличием является то, что мастер-страница должна содержать элемент управления ContentPlaceHolder, который не имеет каких-либо примечательных свойств и предназначен для определения области, куда страница содержимого может вставлять содержимое. При создании новой мастер-страницы элемент ContentPlaceHolder создается по умолчанию, хотя его можно удалить или добавить еще один или несколько. На рис. 6.3 показана только что созданная мастер-страница во время разработки.
Рис. 6.3. Редактирование мастер-страницы в режиме дизайна Для создания страницы в соответствии со структурой, изображенной на рис. 6.1, необходимо выполнить следующие действия:
Для добавления таблицы на страницу можно воспользоваться готовыми шаблонами таблиц, предоставляемых Visual Studio. Для выбора шаблона таблицы и добавления ее на страницу нужно выполнить следующую команду главного меню: Layout р Insert Table. В открывшемся окне Insert Table можно либо указать необходимое количество строк, столбцов, а также некоторые другие параметры таблицы, либо выбрать один из предлагаемых шаблонов, как показано на рис. 6.4.
Рис. 6.4. Окно добавления таблицы на основе шаблона В данном примере выберем шаблон "Header, footer and side", позволяющий создать описанную ранее таблицу. После нажатия на кнопку OK таблица будет добавлена на текущую страницу Исходный код страницы в результате выполнения данной операции будет выглядеть следующим образом: <%@ Master Language="C#" AutoEventWireup="true" CodeFile="MainMasterPage.master.cs" Inherits="MainMasterPage" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div><table border="0" cellpadding="0" cellspacing="0" style="width: 100%; height: 100%"> <tr> <td colspan="2" style="height: 200px"> Верхний колонититул</td> </tr> <tr> <td style="width: 200px"> Меню</td> <td> </td> </tr> <tr> <td colspan="2" style="height: 200px"> Нижний колонтитул</td> </tr> </table> </div> </form> </body> </html> Как видно, в результате данной операции была добавлена обычная HTML-таблица, для которой были установлены значения ширины и высоты некоторых ячеек. В режиме разработки дизайна страница будет выглядеть следующим образом (рис. 6.5):
Рис. 6.5. Редактирование добавленной таблицы в режиме дизайна
Рис. 6.6. Добавление на страницу элемента ContentPlaceHolder
В результате проделанных действий мастер-страница в режиме разработки будет выглядеть следующим образом (рис. 6.7):
Рис. 6.7. Результат изменения мастер-страницы Данная мастер-страница практически готова для использования, т. е. в ней присутствуют все необходимые элементы для того, чтобы отображать содержимое страниц содержимого (фактически для этого нужен только элемент управления ContentPlaceHolder) и необходимый минимум дизайна. Однако, сама по себе мастер-страница не может быть отображена в окне браузера, т. к. она предоставляет необходимые элементы дизайна и расположения элементов управления, входящих в шаблон страницы, странице содержимого, которая и содержит те данные, что должны быть отображены в окне браузера. Поэтому для проверки результатов работы необходимо создать хотя бы одну страницу содержимого. В качестве страницы содержимого используем страницу Default.aspx, добавленную к проекту Web-приложения по умолчанию. Для того чтобы превратить обычную страницу в страницу содержимого, необходимо в качестве значения свойства MasterPageFile страницы указать имя мастер-страницы, а также добавить на страницу элемент управления <asp:Content>. Данный элемент управления отсутствует на панели элементов управления Toolbox, поэтому его можно создать либо вручную, либо одним из следующих способов:
Рис. 6.8. Создание элемента Content с использованием контекстного меню элемента ContentPlaceHolder Исходный код страницы Default.aspx в результате проделанных операций, а также ввода текста "это начальная страница Default.aspx", будет выглядеть следующим образом: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" MasterPageFile="~/MainMasterPage.master" %> <asp:Content ID="Content1" runat="server" ContentPlaceHolderID="ContentPlaceHolder1"> это начальная страница Default.aspx</asp:Content>
Рис. 6.9. Связка вновь добавляемой страницы содержимого с мастер-страницей После того как страница содержимого создана, можно запустить Web-приложение. Результат представлен на рис. 6.10.
Рис. 6.10. Результат работы Web-приложения на основе мастер-страниц Для демонстрации возможностей перехода между страницами произведем следующие изменения. Добавим еще одну страницу содержимого, в которую введем текст, как показано на рис. 6.11. В области меню создадим две ссылки на страницы содержимого.
Рис. 6.11. Страница содержимого с размещенным на ней текстом Фрагмент HTML-кода, содержащего ссылки, выглядит следующим образом: <a href= "Default.aspx">страница1</a><br /> <a href= "Default2.aspx">страница2</a> Теперь при щелчке по ссылке в области ContentPlaceHolder будет загружаться соответствующая страница. Использование мастер-страниц является очень мощным инструментом, позволяющим значительно упростить создание Web-приложения, страницы которого оформлены в едином стиле, и, что также немаловажно, поддержание данного приложения (обновление, добавление элементов, изменение дизайна и т. д.). Тем не менее возникают задачи, решение которых при использовании мастер-страниц вызывает затруднения. К таким вопросам относятся вопросы, связанные с доступом к мастер-странице из кода страницы содержимого, вложением мастер-страниц друг в друга и динамическим заданием мастер-страницы. Создатели Web-приложений знают, что достаточно важное значение в этой разработке играют заголовки страниц, а также строки метадискрипторов, от которых зависит индексация страницы поисковыми роботами. Каким же образом возможно задавать заголовки страниц содержимого, ведь они фактически вкладываются в мастер-страницу? Сделать это можно двумя способами - либо задав заголовок страницы в атрибуте Title директивы Page страницы содержимого, как показано ниже, <%@ Page Language="C#" AutoEventWireup="true" CodeFile= "Default.aspx.cs" Inherits="_Default" MasterPageFile="~/MasterPages/ MainMasterPage.master" Title="Первая страница сайта" %> либо обратившись к заголовку страницы из программного кода. Для этого необходимо получить ссылку на объект Page для мастер-страницы, к которой возможно обращаться из процедуры обработки загрузки текущей страницы следующим образом. Page masterPage = base.Master.Page; masterPage.Header.Title = "заголовок установлен программно"; Еще одним примером необходимости обращения к мастер-странице из программного кода страниц содержимого является необходимость модификации содержимого мастер-страницы в зависимости от текущих режимов или обращения к определенной странице содержимого. Самым простым примером в данном случае является необходимость изменения баннера мастер-страницы в зависимости от того, к какой странице содержимого обратился пользователь. Модифицируем предыдущий пример таким образом, чтобы при обращении к странице Default.aspx с помощью гиперссылки "страница1" в верхней части мастер-страницы отображался текст "Пример обращения к мастер-странице", а при обращении к странице Default2.aspx - текст "Прямой доступ к мастер-странице". При этом рассмотрим различные способы организации доступа к элементам управления, расположенным на мастер-странице. В первую очередь внесем изменения в саму мастер-страницу, добавив элемент Label в верхнюю ее часть. Значение ID этого элемента установим равным lbl_BannerText. Для обращения к ресурсам мастер-страницы можно использовать либо прямое обращение к ее элементам управления, что нарушает принципы объектного подхода к разграничению прав доступа, либо создать необходимые свойства в классе мастер-страницы. Добавим свойство BannerText в класс мастер-страницы. Исходный текст свойства выглядит следующим образом: public string BannerText { get { return lbl_BannerText.Text; } set { lbl_BannerText.Text = value; } } Теперь становится возможным обратиться к свойству BannerText из любой страницы содержимого, использующей в качестве мастер-страницы данную. Для этого необходимо выполнить следующие действия:
Возможен и другой способ обращения к элементам управления мастер-страницы. Он очень похож на предыдущий, с той разницей, что тип объекта, возвращаемого с помощью свойства Master, приводится к типу данной мастер-страницы. Приведение типа необходимо, т. к. свойство Master возвращает объект обобщенного типа MasterPage. Естественно, данный объект не содержит тех свойств (в данном случае это BannerText), которые мы ввели в класс конкретной мастер-страницы. В предыдущем примере приведение не требовалось, т. к. ссылка на тип была доступна через директиву MasterType. Исходный код обращения к свойству BannerText мастер-страницы MainMasterPage будет выглядеть следующим образом: MainMasterPage master=(MainMasterPage) Master; master.BannerText= Пример обращения к мастер-странице"; При использовании программного обращения к мастер-странице необходимо учесть следующее. При переходе от одной странице к другой, как известно, все объекты Web-страницы создаются заново. Это означает, что при переходе от одной страницы содержимого к другой, использующей ту же мастер-страницу, последняя создается снова. Поэтому при необходимости сохранения значения свойств и значений элементов управления мастер-страницы нужно использовать cookie-наборы, текстовые файлы, базы данных либо любые другие возможности долговременного хранения данных, и каждый раз программно осуществлять инициализацию мастер-страницы. Еще одной возможностью для доступа к элементам мастер-страницы является прямой доступ к ним. Для демонстрации возможностей данного способа создадим пример, в котором страница содержимого Default2.aspx будет изменять текст баннера мастер-страницы на следующий: "Прямой доступ к мастер-странице". Для этого создадим в обработчике события Page_Load страницы Default2.aspx следующий код: Label lbl = Master.FindControl("lbl_BannerText") as Label; if (lbl != null) lbl.Text = "Прямой доступ к мастер-странице"; Как видно из данного примера, сначала происходит поиск элемента управления lbl_BannerText, и, в случае успеха, устанавливается значение свойства Text. При построении достаточно сложного Web-приложения может потребоваться изменение мастер-страницы во время выполнения. Это особенно актуально в случае, когда внешний вид страницы должен меняться в зависимости от действий пользователя, например в зависимости от того, какой пользователь прошел авторизацию в системе, либо если необходимо предусмотреть возможность настройки внешнего вида приложения в зависимости от предпочтений пользователя. В любом из этих случаев для реализации данной функциональности можно создать несколько мастер-страниц, которые затем переключать в зависимости от действий пользователя. Для изменения текущей мастер-страницы программным способом необходимо задать имя файла новой мастер-страницы в свойстве Page.MasterPageFile. Делать это можно в событии Page.Prelnit страницы содержимого. При этом нужно учесть следующее: мастер-страницы, на которые будут переключаться страницы содержимого, должны быть "совместимы" друг с другом. Т. е. они должны содержать одинаковые элементы управления (одинакового типа, с одинаковыми значениями ID), в противном случае произойдет ошибка при попытке обращения к какому-либо из них. Кроме того, если страница содержимого, для которой предполагается динамическое изменение мастер-страницы, должна программно обращаться к элементам мастер-страницы, это обращение необходимо осуществлять напрямую, без применения строго типизированного подхода на основе создания свойств мастер-страницы, как было показано ранее. При этом использовать директиву <%@ MasterType %> нежелательно. В качестве примера добавим к предыдущему примеру еще одну мастер-страницу OtherMasterPage, которая будет содержать те же элементы управления, что и MainMasterPage, однако ее оформление будет выглядеть так, как показано на рис. 6.12.
Рис. 6.12. Вторая мастер-страница, добавленная к Web-приложению Добавим в обе мастер-страницы кнопку "Изменить мастер-страницу", ID которой равно btn_ChangeMasterPage. Обработчик события этой кнопки для обеих мастер-страниц будет одинаковым. protected void btn_ChangeMasterPage_Click(object sender, EventArgs e) { if (Request.Browser.Cookies) { if (Request.Cookies["masterpage"] != null) { if (Request.Cookies["masterpage"].Value == "1") Response.Cookies["masterpage"].Value = "2"; else Response.Cookies["masterpage"].Value = "1"; } else { HttpCookie mpage = new HttpCookie("masterpage"); mpage.Expires = DateTime.Now.AddDays(1); mpage.Value = "2"; Response.Cookies.Add(mpage); } } Response.Redirect(Request.RawUrl); } Как видно, здесь применяется механизм Cookies для запоминания текущей мастер-страницы, а также задания той из них, которая будет использоваться в качестве текущей. Сам cookie назван masterpage. При значении masterpage=1 активной будет мастер-страница MainMasterPage, при masterpage=2 - OtherMasterPage. Команда Response.Redirect (Request.RawUrl); необходима для того, чтобы перегрузить текущую страницу, изменив, таким образом, ее внешний вид за счет подключения другой мастер-страницы. Само подключение другой мастер-страницы происходит в обработчике события Page.PreInit каждой страницы содержимого. В данном примере для обеих страниц содержимого, хранящихся в файлах Default.aspx и Default2.aspx, создан одинаковый обработчик события Page.PreInit, исходный код которого приведен ниже. protected void Page_PreInit(object sender, EventArgs e) { if (Request.Browser.Cookies) if (Request.Cookies["masterpage"] != null) if (Request.Cookies["masterpage"].Value == "1") { Page.MasterPageFile = "~//MasterPages// MainMasterPage.master"; } else { Page.MasterPageFile = "~//MasterPages// OtherMasterPage.master"; } } В зависимости от значения cookie masterpage устанавливается текущая мастер-страница. В результате при нажатии на кнопку Изменить мастер-страницу оформление текущей страницы изменится, а содержимое останется прежним (рис. 6.13).
Рис. 6.13. Пример динамического изменения мастер-страницы Еще одним из важных свойств мастер-страниц является возможность вложения одной мастер-страницы в другую. Обычно эта возможность используется не часто, однако является хорошим средством стандартизировать Web-приложение. Следует помнить, что при использовании вложенных мастер-страниц редактирование страниц второго и более низких уровней в визуальном режиме невозможно. В общем случае возможно бесконечное количество вложений мастер-страниц, однако на практике не рекомендуется использовать более одного уровня. Это связано с тем, что при необходимости изменения верхнего, общего для всех страниц колонтитула придется перестраивать всю иерархию мастер-страниц, что является довольно сложной процедурой, способной доставить много неприятностей в процессе отладки приложения. Поэтому рекомендуется использовать один уровень мастер-страниц, а общие элементы переносить с помощью копирования. В качестве примера создадим иерархию из двух мастер-страниц и одной страницы содержимого. Верхний уровень мастер-страниц содержит верхний колонтитул, общий для всего приложения. Следующий уровень мастер-страницы добавляет область меню в левой части окна. Страница содержимого же содержит пример содержимого страницы и связана с мастер-страницей второго уровня. Исходные коды всех трех страниц приведены ниже. Мастер-страница верхнего уровня (RootMasterPage.master): <%@ Master Language="C#" AutoEventWireup="true" CodeFile="RootMasterPage.master.cs" Inherits="RootMasterPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div> <table border="0" cellpadding="0" cellspacing="0" style="width: 100%; height: 100%"> <tr> <td style="height: 7px"> <h1>Общий заголовок для всех страниц Web-приложения</h1> </td> </tr> <tr> <td> <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server"> </asp:ContentPlaceHolder> </td> </tr> </table> </div> </form></body></html> Мастер-страница второго уровня (Node1MasterPage.master): <%@ Master Language="C#" AutoEventWireup="true" CodeFile="Node1MasterPage.master.cs" Inherits="Node1MasterPage" MasterPageFile="~/MasterPages/RootMasterPage.master" %> <asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server"> <table border="0" cellpadding="0" cellspacing="0" style="width: 100%; height: 100%"> <tr> <td style="height: 200px;background-color: lightgrey;"> Здесь располагается меню </td> <td> <asp:ContentPlaceHolder ID="CPH2" runat="server"> </asp:ContentPlaceHolder> </td> </tr> </table> </asp:Content> Страница содержимого (Default3.aspx): <%@ Page Language="C#" MasterPageFile="~/MasterPages/ Node1MasterPage.master" AutoEventWireup="true" CodeFile="Default3.aspx.cs" Inherits="Default3" Title= "Untitled Page" %> <asp:Content ID="Content1" ContentPlaceHolderID="CPH2" Runat="Server"> <h3>содержимое вложенной мастер-страницы</h3> </asp:Content> В результате выполнения приложения окно браузера будет выглядеть следующим образом:
Рис. 6.14. Результат выполнения приложения, содержащего вложенные мастер-страницы Краткие итоги В настоящее время Web-приложения редко создаются "с нуля", обычно для из создания используются готовые шаблоны. Эти шаблоны необходимы для оформления множества различных страниц, составляющих интернет-приложение, в едином стиле. В ASP.NET реализован эффективный механизм создания и использования таких шаблонов - мастер-страницы. Обычно мастер-страница содержит фиксированные элементы, одинаковые для всех страниц, и заполнитель содержимого для остальной части страницы. В момент обращения пользователя к странице Web-приложения среда ASP.NET осуществляет проверку принадлежности данной страницы к какой-либо мастер-странице. В случае положительного результата страница содержимого получает от мастер-страницы фиксированные элементы и предоставляет дополнительное содержимое. Сформированная таким образом страница передается клиенту для отображения в браузере. Таким образом, мастер-страница не может быть отображена в окне браузера клиента, т. к. она содержит элементы, используемые для формирования страницы содержимого и отправки ее клиенту. К мастер-странице можно обращаться из программного кода. Такая необходимость может потребоваться для динамической модификации мастер-страницы в зависимости от текущих режимов или обращения к определенной странице содержимого. Существует возможность вложения одной мастер-страницы в другую. При этом исключается возможность визуального редактирования второй мастер-страницы, а также мастер-страниц более низкого уровня. В общем случае допускается бесконечное количество вложений мастер-страниц, однако на практике не рекомендуется использовать более одного уровня. |