Использлвание Master Pages в Microsoft ASP.NET 2.0

К началу раздела

Глава 8. Использование Master Pages в Microsoft ASP.NET

Master Pages (мастер-страницы) - технология Microsoft, впервые появившаяся в ASP.NET 2.0. Эта технология позволяет создать предопределенную компоновку страниц (например, заголовок (шапку), меню, поля для отображения информации, счетчики ...) и многократно применять ее к разным страницам приложения, наполняя элементы компоновки тем содержимым, которого требует контент страницы.


В начало

Параграф 1. Методика создания и использования Master Pages

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

Создадим обычным образом решение сайта (File/New/WebSite), после чего удалим из директивы "Page" все, кроме самой директивы и параметра "Language" (можно, при желании, удалить и файл Default.aspx.cs, если основная страница будет отображать только то, что ей предоставят мастер-страница и страницы контента):

<%@ Page Language="C#">

Добавим мастер-страницу к решению, для чего, в контекстном меню Solutation Explorer узла решения выбираем пункт "Add New Item" (Рис.1). Задаем "Templates" - "Master Page", определяем "Name" - имя мастер-страницы, задаем "Language", ставим галочку в чекбоксе "Place code in separate file" и нажимаем кнопку ADD. В Solutation Explorer появился узел, состоящий из двух файлов - MasterPage.master и MasterPage.master.cs (Рис.1). Это и есть наша мастер страница.

pagemaster0001.gif

Рис.1 Добавление мастер страницы к решению

Мастер-страница может содержать HTML код страницы и может содержать любые контролы, сценарии и т.п., то есть все, что может содержать любая Web страница. Кроме того, мастер-страница (и только она и страницы, для которых она является старшей) может содержать (или не содержать) контролы ContentPlaceHolder. Этот элемент определяет область, которая может быть переопределена страницей, вызываемой из мастер-страницы.

Рассмотрим содержимое файлов шаблона мастер страницы:

Код в файле MasterPage.master имеет директиву "Master" ( вместо директивы "Page") - в остальном, он мало отличаются от кода обычной Web страницы. Новым может быть лишь появление контрола "ContentPlaceHolder" - это элемент определяет область, которая может быть переопределена конкретной страницей содержимого.

<%@ Master Language="C#" AutoEventWireup="true" 
  CodeFile="MasterPage.master.cs" Inherits="MasterPage" %>
<!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>

        <asp:contentplaceholder id="ContentPlaceHolder1" 
                                           runat="server">
        </asp:contentplaceholder>

    </div>
    </form>
</body>
</html>

Прикрепленный код в MasterPage.master.cs, говорит о том, что класс MasterPage является наследником класса System.Web.UI.MasterPage. В нем мы можем выполнять любые действия на стороне сервера, как и для обычной страницы.

public partial class MasterPage : System.Web.UI.MasterPage
{
 protected void Page_Load(object sender, EventArgs e)
 {
 }
}

Осталось добавить нашу мастер-страницу к файлу решения, для чего, в файле Default.aspx добавляем параметр MasterPageFile="~/MasterPage.master":

<%@ Page Language="C#" MasterPageFile="~/MasterPage.master" %>

Обратим внимание, что значение параметра MasterPageFile начинается с ~/. Это означает, что мастер страница находится не в предопределенной папке MasterPages, а в корневой директории решения (хотя, можно и создать такую папку). Причина отсутствия тэгов <html>, <head>, <title>, <body> - они уже есть в мастер-странице и ни в одной другой странице решения быть не могут.

Мастер страницу можно добавлять в решение и через включение объявления в web.config (<pages masterPageFile="MasterPage.master" />), но, в силу ряда недостатков и ограничений, этот путь не рекомендован разработчиками.

Если выполнить решение на данном этапе, то в браузере отобразится пустая страница. Для того, чтобы страница не была пустой, наполним мастер страницу некоторым содержанием.

Добавим страницы "main" и "warehouse" к решению, для чего, в контекстном меню Solutation Explorer узла решения выбираем пункт "Add New Item". Задаем Templates - Web Form, определяем "Name" (имя "main" и "warehouse" соответственно), определяем "Language" - "VisualC#", ставим галочку в чекбоксе "Place code in separate file" и в чекбоксе "Select Master Page", нажимаем кнопку ADD. После выбора MasterPage.master (он пока у нас один) в окне Select a Master Page в Solutation Explorer появятся узлы, состоящие из двух файлов с расширениями, как и у обычной страницы (.aspx, aspx.cs).

Далее сформируем HTML код мастер страницы (рекомендуется просто перенести следующий код в "master.aspx" файл и посмотреть разметку в дизайнере формы):

<%@ Master Language="C#" AutoEventWireup="true" 
 CodeFile="MasterPage.master.cs" Inherits="MasterPage" %>
<!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>Домашняя страничка</title>
    <asp:ContentPlaceHolder id="head" runat="server">    
    </asp:ContentPlaceHolder>
</head>
<body>
    <form id="form1" runat="server">
    <table border="1" width="50%">
    <tr><th colspan="2" style="color:#800000">Trade firm OOO 
        "Horns and hoofs"</th></tr>
       <tr>              
      <td id="menu">
        <asp:LinkButton ID="LinkButton1" runat="server" 
             PostBackUrl="~/main.aspx">О нашей фирме</asp:LinkButton>
        <br />
        <asp:LinkButton ID="LinkButton2" runat="server" 
          PostBackUrl="~/warehouse.aspx">Что еа складе</asp:LinkButton>
      </td>      
      <td id="main">
        <asp:contentplaceholder id="ContentPlaceHolder1" 
                                           runat="server"> 
        </asp:contentplaceholder>
      </td>
      </tr>              
      <tr> 
      <td colspan="2" style="text-align:center">             
      <asp:Label ID="Label1" runat="server" 
                 Text="Label"></asp:Label>
      </td>
      </tr>              
     </table>     
    </form>
</body>
</html>

Здесь мы ввели в качестве элемента разметки таблицу, хотя можно использовать и другие тэги, например, тэг "div". Файлы "main.aspx" и "warehouse.aspx" - это страницы, которые должны переопределять содержимое contentPlaceHolder1. Они имеют расширение ".aspx", как и обычные страницы. В тоже время, если файлы ".aspx.cs" ничем не отличаются от обычных файлов прикрепленного кода, то файлы ".aspx" имеют одну особенность - элементы "asp:Content" (для файла main.aspx):

<%@ Page Language="C#" 
  MasterPageFile="~/MasterPage.master" 
   AutoEventWireup="true" CodeFile="main.aspx.cs" 
         Inherits="main" Title="Untitled Page" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" 
  ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
</asp:Content>

Все, что будет помещено внутри тэга "asp:Content" с ID="Content2" при вызове страниц "main.aspx" и "warehouseaspx" будет включено (поместится, заменит) области мастер страницы в элементах управления "ContentPlaceHolder". Ясно, что "asp:Content" c ID="Content1" предназначен для включения в мастер страницу элементов тэга "Head" (например, таблиц стилей). Это означает, что все, что мы хотим включить в мастер-страницу должно находиться в страницах содержимого в пределах элементов управления Content c ID="Content2". Внутри же их, мы можем помещать все, что допустимо в обычных страницах, например контролы "Label", "TextBox", "Button"..., создавать обработчики событий элементов:

<%@ Page Language="C#" MasterPageFile="~/MasterPage.master" 
 AutoEventWireup="true" CodeFile="main.aspx.cs" 
  Inherits="main" Title="О нашей фирме" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" 
 ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
   <div style ="text-align:center">
   <asp:Label ID="Label1" runat="server" 
         Text="Руководитель фирмы:"></asp:Label>        
    <br/>
    <asp:TextBox ID="TextBox1" runat="server" 
     Width="233px"></asp:TextBox>
    <br/>         
    <asp:Button ID="Button1"
        runat="server" Text="Узнай кто!" onclick="Button1_Click" />    
	 </div>
</asp:Content>

В дизайнере формы мастер страница и страница "main.aspx" выглядят, как показано на Рис.2.

pagemaster0002.gif

Рис.2 Мастер страница и страница содержания "main.aspx"

Как видно из рисунка, уже на этапе разработки формы страницы содержания включаются в мастер-страницу и составляет с ней как бы одно целое. Иначе (в нашем примере), cодержимое "суммарной" страницы будет меняться в зависимости от вызова и контента вызываемых по гиперссылкам страниц - "main.aspx" или "warehouse.aspx". И, кроме того, можно использовать код и в мастер-странице, например:

public partial class MasterPage : System.Web.UI.MasterPage
{
 protected void Page_Load(object sender, EventArgs e)
 {
  Label1.ForeColor = Color.Red;
  Label1.Text = "Наша фирма лучшая в мире!";
 }
}

Добавления серверного кода в страницах содержимого выполняется обычным образом:

public partial class main : System.Web.UI.Page
{
 protected void Page_Load(object sender, EventArgs e)
 {
 }
 protected void Button1_Click(object sender, EventArgs e)
 {
   TextBox1.Text = "Нет, это не О.Бендер!";
 }
}

Для кода страницы "warehouse.aspx.cs" ограничимся просто выводом текста:


<%@ Page Language="C#" MasterPageFile="~/MasterPage.master" 
 AutoEventWireup="true" CodeFile="warehouse.aspx.cs" 
  Inherits="warehouse" Title="РЎРєР>Р°Р_" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">    
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" 
 Runat="Server"> 
    <div style="text-align:center" >
<asp:TextBox ID="TextBox1" runat="server" Text="Рогов: 2, Копыт: 4." >
 </asp:TextBox>
</div>
</asp:Content>  

Теперь, при старте, будет выведен текст "Наша фирма лучшая в мире!" и, далее, при выборе ссылок, получим результат, показанный на Рис.3.

Обратим внимание, что основная страница наследует не только содержимое контентов, но и заглавие ("Title") страницы.

pagemaster0003.gif

Рис.3. Выполнение решения сайта


В начало

Параграф 2. Вложенные мастер страницы

Web сайт может содержать множество мастер-страниц и есть возможность вкладывать одни мастер-страницы в другие.

Покажем множественное наследование мастер-страниц, для чего, несколько изменим решение:

  • Вначале добавим к решению еще одну мастер-страницу (также, как мы добавили первую). В решении появятся узлы "MasterPage2.master" и "MasterPage2.master.cs".

  • Изменим файл "Default.aspx" так, что для него теперь мастер-страницей будет "MasterPage2.master".

    <%@ Page Language="C#" MasterPageFile="~/MasterPage2.master" %>
    
  • В "MasterPage2.master" запишем код:

    <%@ Master Language="C#" AutoEventWireup="true" 
     CodeFile="MasterPage2.master.cs" Inherits="MasterPage2" 
     MasterPageFile="~/MasterPage.master" %>
    <!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>
        <asp:ContentPlaceHolder id="head" runat="server">
        </asp:ContentPlaceHolder>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
    <asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server">
            Это стартовая страница
        <br/><br/>    
        <asp:Label ID="Label1" runat="server" 
     Text="Здесь можно выполнить ряд других действий в MasterPage2.master.cs">
     </asp:Label>
     <br/><br/>    
     <asp:Button ID="Button1" runat="server" Text="Я с master2, нажми меня!" 
             onclick="Button1_Click" />
    </asp:ContentPlaceHolder>
        </div>
        </form>
    </body>
    </html>
    

В "MasterPage2.master,cs" запишем код обработчика нажатия кнопки:

public partial class MasterPage2 : System.Web.UI.MasterPage
{
  protected void Button1_Click(object sender, EventArgs e)
  {
    Label1.ForeColor = Color.Red;
    Label1.Text = "Сдавайте свои рога и копыта, господа!";
  }
  .....
}

Результат:

pagemaster0004.gif

Рис.4. Использование вложенных мастер-страниц

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

Далее, результат выполнения решения будет полностью аналогичен предыдущему примеру (Рис.3.).


В начало

Параграф 3. Логотипы в Master Pages

Добавим рисунок в решение, для чего в контекстном меню Solutation Explorer узла решения выбираем пункт "Add Existing Item", выберем рисунок, помещенный в директорию решения. Вместо надписи "Trade firm OOO 'Horns and hoofs'" внесем ссылку на рисунок, как показано ниже (рекомендуется просто перенести следующий код в "master.aspx" файл и посмотреть разметку в дизайнере формы - Рис.5.):

<%@ Master Language="C#" AutoEventWireup="true" 
 CodeFile="MasterPage.master.cs" Inherits="MasterPage" %>
<!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>Домашняя страничка</title>
    <asp:ContentPlaceHolder id="head" runat="server">    
    </asp:ContentPlaceHolder>
</head>
<body>
    <form id="form1" runat="server">
    <table border="1" width="50%">
    <tr><th colspan="2" style="color:#800000">
       <img src="a01.gif" alt="a01.gif" />
       </th></tr>
       <tr>              
      <td id="menu">
        <asp:LinkButton ID="LinkButton1" runat="server" 
             PostBackUrl="~/main.aspx">О нашей фирме</asp:LinkButton>
        <br />
        <asp:LinkButton ID="LinkButton2" runat="server" 
          PostBackUrl="~/warehouse.aspx">Что еа складе</asp:LinkButton>
      </td>      
      <td id="main">
        <asp:contentplaceholder id="ContentPlaceHolder1" 
                                           runat="server"> 
        </asp:contentplaceholder>
      </td>
      </tr>              
      <tr> 
      <td colspan="2" style="text-align:center">             
      <asp:Label ID="Label1" runat="server" 
                 Text="Label"></asp:Label>
      </td>
      </tr>              
     </table>     
    </form>
</body>
</html>

pagemaster0005.gif

Рис.5. Решение с логотипом

Результат - на всех страницах сайта будет присутствовать наш рисунок (Рис.6.):

pagemaster0006.gif

Рис.6. Использование логотипов в Master Pages

Если используется HTML тэг "img" (ровно, как и тэги "a"), то при развертывании приложения придется использовать полный относительный путь к рисунку (включая доменное имя), поэтому рекомендуется использовать преобразование элемента к серверному (runat="server"). В этом случае, сервер преобразует элемент к серверному "HtmlImage" и, поскольку этот объект создается после объекта "Page" (при создании мастер страницы), то Asp.Net будет интерпретировать все пути относительно мастер страницы.

 
<img src="MasterPages/a01.gif" alt="a01.gif" runat="server"/>
//Можно и так
<img src="~/MasterPages/a01.gif" alt="a01.gif" runat="server"/>


В начало

Параграф 4. Изменение и добавление контентов

Если мы удалим элемент "Conten" со страницы содержимого, например из файла "main.aspx", то, в силу наличия в директиве "Page" свойства MasterPageFile="~/MasterPage.master", "ContentPlaceHolder1" будет отображен в дизайнере для страницы "main.aspx" (в виде серого квадратика), но без содержимого. Для добавления "Content", кликнем мышкой на треугольничке в правом верхнем углу элемента "ContentPlaceHolder1" и в контекстном меню (левый клик - появляется как многострочное, или правый клик - двух строчное) выбираем пункт "Create Custom Content". Элемент "Content" будет добавлен к странице (Рис.7.).

<asp:Content ID="Content1" runat="server" 
    contentplaceholderid="ContentPlaceHolder1">       
</asp:Content>

Если потребуется удалить контент, то необходимо выбрать пункт "Default to Mastr's Content".

pagemaster0007.gif

Рис.7. Добавление и удаление элементов Content


В начало

Параграф 5. Значение контента по умолчанию

Изначально "ContentPlaceHolder" мастер страницы пуст:

<td id="main">
 <asp:contentplaceholder id="ContentPlaceHolder1" runat="server"> 
    </asp:contentplaceholder>
</td>

Уберем со страницы "warehouse.aspx", а на мастер странице в "ContentPlaceHolder1" добавим контрол "TextBox":

<td id="main">
 <asp:contentplaceholder id="ContentPlaceHolder1" runat="server"> 
   <asp:TextBox ID="TextBox1" Text="Рогов: нет. Копыт: нет." runat="server"></asp:TextBox>
    </asp:contentplaceholder>
</td>

Выполним решение и убедимся, что "TextBox" и его содержимое со страницы мастер окажутся встроенными в страницу "warehouse.aspx" (другие страницы ведут себя, как и ранее). Таким образом, при неопределенном контенте страниц содержимого "ContentPlaceHolder" страницы заполняется содержимым по умолчанию из "ContentPlaceHolder" мастер-страницы (Рис.8.).

pagemaster0008.gif

Рис.8. Контент по умолчанию

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


В начало

Параграф 6. Динамическое задание мастер страницы

Asp.Net загружает мастер-страницу сразу после генерации события "PreInit". Таким образом, для того, чтобы иметь возможность изменять мастер страницу программно, необходимо выполнять это в событии "Page_PreInit". Задание выполняется просто. В предыдущем примере можно убрать в файле "Default.aspx" в директиве "Page" атрибут "MasterPageFile" и поместить его в качестве кода в обработчик события "PreInit". Мастер-страницей в обработчике события "PreInit" зададим "MasterPage2.aspx". Выполнив решение, мы получим результат тот же, что мы видели на Рис.4. Даже если не будем убирать связь с другой мастер страницей в директиве "Page", то результат не изменится.

<%@ Page Language="C#" MasterPageFile="~/MasterPage.master" %>
<script runat="server">
 protected void Page_PreInit(object sender, EventArgs e)
 {
  MasterPageFile = "~/MasterPage2.master";
 }
</script>

Молчанов Владислав 21.3.2006г.

Еcли Вы пришли с поискового сервера - посетите мою главную страничку

На главной странице Вы найдете программы комплекса Veles - программы для автолюбителей, программу NumberPhoto, созданную для работы с фото, сделанными цифровым фотоаппаратом, программу Локальный Web сайт - предназначенную для просмотра и прослушивания файлов большинства графических и звуковых форматов в Web Browser, программу Bricks - игрушку для детей и взрослых, программу записную книжку, программу TellMe - говорящий Русско-Английский разговорник - программу для тех, кто собирается погостить за бугром или повысить свои знания в английском, теоретический материал по программированию в среде Borland C++ builder, C# (Windows приложения и ASP.Net Web сайты).

В начало страницы

К началу раздела

В начало книги

На главную страницу сайта


Сайт управляется системой uCoz