| Украина, Киев |
Стилевое оформление страниц
Первый способ
-
Двойным
щелчком на
свободном от элементов управления месте мастер-страницы Title.master в
режиме Design (или вручную)
создайте блок скриптов, который заполните так
<%@ Master Language="C#" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
}
public string MyHeader1
{
get { return Header1.InnerText; }
set { Header1.InnerText = value; }
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Мастер-страница Title.master</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" runat="server" id="Header1">
Мы приветствуем Вас на нашем сайте!!!
</h1>
.............................................
</div>
</form>
</body>
</html>
Листинг
31.54.
Добавление свойства доступа к дескриптору <h1> в файле Title.master
-
Дополните
контекстную страницу SatelliteExt.aspx следующим
кодом
<%@ Page Language="C#" MasterPageFile="~/MasterPages/Title.master"
Title="Декларативный заголовок SatelliteExt.aspx" %>
<%@ MasterType VirtualPath="~/MasterPages/Title.master" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
// Получаем ссылку на мастер-страницу
Page masterPage = Master.Page;
// Переопределяем строку заголовка
masterPage.Header.Title = "Программный заголовок SatelliteExt.aspx";
// Управляем дескриптором h1
Master.MyHeader1 = "Это программно подмененный"
+ " заголовок мастер-страницы (способ 1)!";
}
</script>
Листинг
31.55.
Дополненный код контекстной страницы SatelliteExt.aspx
-
Исполните
контекстную страницу SatelliteExt.aspx и
убедитесь, что дескриптор <h1>,
относящийся к заполнителю мастер-страницы, подменяется
нашим текстом
Директива @ MasterType указывает ASP.NET виртуальный путь к соответствующему файлу мастер-страницы. Без нее доступ к объявленному свойству будет неопределен.
Второй способ
-
Измените
контекстную страницу SatelliteExt.aspx следующим
образом
<%@ Page Language="C#" MasterPageFile="~/MasterPages/Title.master"
Title="Декларативный заголовок SatelliteExt.aspx" %>
<%@ MasterType VirtualPath="~/MasterPages/Title.master" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
// Получаем ссылку на мастер-страницу
Page masterPage = Master.Page;
// Переопределяем строку заголовка
masterPage.Header.Title = "Программный заголовок SatelliteExt.aspx";
// Управляем дескриптором h1
// Master.MyHeader1 = "Это программно подмененный"
// + " заголовок мастер-страницы (способ 1)!";
HtmlGenericControl h1 = Master.FindControl("Header1") as HtmlGenericControl;
if (h1 != null)
{
h1.InnerText = "Это программно подмененный"
+ " заголовок мастер-страницы (способ 2)!";
}
}
</script>
Листинг
31.56.
Измененный код контекстной страницы SatelliteExt.aspx
Метод FindControl() ищет указанный элемент на мастер-странице среди элементов заданного типа, и если находит, то возвращает контекстной странице ссылку на этот элемент. Затем уже мы обращаемся к конкретным свойствам этого элемента.
-
Исполните
страницу SatelliteExt.aspx и
убедитесь, что дескриптор <h1>,
относящийся к заполнителю мастер-страницы, подменяется
нашим текстом
Второй способ более предпочтительный, поскольку мы не вмешиваемся в код спроектированной мастер-страницы, которая может быть подключена еще к чему-нибудь. Мы в мастер-странице просто заранее преобразуем некоторые элементы в серверные (управляемые на стороне сервера) и присваиваем им идентификаторы для дальнейшей адресации из кода контекстной страницы.
Упражнение 16. Программное переключение мастер-страниц
Иногда может возникнуть необходимость дать возможность пользователю подключать необходимые мастер-страницы. Мы уже рассматривали подобный способ, когда говорили о динамическом подключении тем. Там мы программно определяли значение атрибута Page.Theme в директиве @Page. Теперь нам нужно программно менять атрибут Page.MasterPageFile в коде контекстной страницы.
Здесь нужно иметь ввиду следующее:
- Контекстная страница, динамически меняющая шаблон, не должна иметь контекстных блоков, ссылающихся на несуществующие в новой мастер-странице контейнеры ContentPlaceHolderID
- Замена шаблона должна выполняться в обработчике события Page.PreInit контекстной страницы. Если это сделать в обработчиках более поздних событий, то будет сгенерировано исключение
- Все контекстные страницы, на которые имеются ссылки в текущей странице содержимого, должны иметь код подключения выбранного шаблона
- Для межстраничной передачи информации о выбранном шаблоне ее нужно где-то сохранять. Как и в случае с темами, это могут быть скрытые поля состояния вида (VIEWSTATE), глобальные объекты уровня сессии или приложения
Учитывая, что наши страницы Satellite.aspx, Satellite1.aspx, Satellite2.aspx, Satellite3.aspx согласованы с Title.master, сделаем их копии и настроим под динамическую смену мастер-страниц.
-
В
панели Solution Explorer создайте копию файла Title.master с
именем Title1.master
-
Откройте
мастер-страницу Title1.master и
добавьте выше объекта ImageBanner (после
открывающего дескриптора <div> )
элемент ContentPlaceHolder с
именем ContentPlaceHolderList
-
Добавьте
к гиперссылкам HyperLink еще
одну с названием " Автошкола
в целом " -
Сохраните
и закройте файл Title1.master
-
В
панели Solution Explorer создайте
копию файла Title1.master с
именем Title2.master
-
Сделайте
копии файлов контекстных страниц Satellite?.aspx и
присвойте им имена SatelliteDynamic.aspx, SatelliteDynamic1.aspx, SatelliteDynamic2.aspx, SatelliteDynamic3.aspx и SatelliteDynamic4.aspx соответственно -
Определите
страницу SatelliteDynamic.aspx стартовой -
Откройте
мастер-страницу Title2.master и
выполните в ней следующее:- Полностью удалите контейнер скриптов <script runat="server">...</script>
- Удалите объект ImageBanner и внесите еще какие-нибудь визуально отличимые изменения
- Заполните свойство NavigateUrl гиперссылок адресами новых контекстных страниц, а ссылку " Автошкола в целом " адресуйте на SatelliteDynamic.aspx
-
В
панели Solution Explorer выделите
сразу все контекстные страницы SatelliteDynamic?.aspx и
откройте их в режиме Source,
чтобы вручную
заменить атрибут MasterPageFile="~/MasterPages/Title.master" на MasterPageFile="~/MasterPages/Title1.master"
-
Откройте
контекстную страницу SatelliteDynamic.aspx и
в режиме Design создайте контейнер
содержимого для шаблона ContentPlaceHolderList,
выполнив на нем команду Create Custom
Content контекстного меню -
Добавьте
в контейнер контекста предваряющий текст " Выберите
мастер-страницу:" и элемент DropDownList с
именем lstMasterPages
-
Заполните
раскрывающийся список lstMasterPages так
| Text | Value | |
|---|---|---|
| Items[0] | Мастер-страница с баннером | ~/MasterPages/Title1.master |
| Items[1] | Мастер-страница без баннера | ~/MasterPages/Title2.master |
-
Установите
для списка lstMasterPages свойство AutoPostBack="True"
-
В
режиме Design двойным
щелчком на тускло просвечивающемся заполнителе
мастер-страницы создайте контейнер для скриптов,
обработчик Page_Load() и
переименуйте его в Page_Init()
-
Скопируйте
заготовку обработчика Page_Init() и
переименуйте копию в Page_PreInit(),
поскольку все они имеют одинаковую сигнатуру
-
В
режиме Design двойным щелчком
на объекте lstMasterPages списка
создайте обработчик изменения выбора опции с
именем lstMasterPages_SelectedIndexChanged()
-
Заполните
обработчики, чтобы окончательный код страницы
был таким
<%@ Page Language="C#" MasterPageFile="~/MasterPages/Title1.master" Title="Untitled Page" %>
<script runat="server">
protected void Page_Init(object sender, EventArgs e)
{
if (Session["index"] != null)
{
// Восстанавливаем новое состояние списка
lstMasterPages.SelectedIndex = (int)Session["index"];
}
}
protected void Page_PreInit(object sender, EventArgs e)
{
if (Session["Master"] != null)
{
// Был ранее сохраненный выбор, включить его
Page.MasterPageFile = (string)Session["Master"];
}
}
protected void lstMasterPages_SelectedIndexChanged(object sender, EventArgs e)
{
// Запоминаем новый выбор пользователя
Session["Master"] = lstMasterPages.SelectedValue;
// Запоминаем новое состояние списка
Session["index"] = lstMasterPages.SelectedIndex;
// Обновляем страницу без полного цикла,
// чтобы новая мастер-страница вступила в действие
Server.Transfer(Request.FilePath);
}
</script>
<asp:Content ID="Content1" runat="server" ContentPlaceHolderID="ContentPlaceHolderList">
Выберите мастер-страницу:
<asp:DropDownList ID="lstMasterPages" runat="server"
OnSelectedIndexChanged="lstMasterPages_SelectedIndexChanged"
AutoPostBack="True">
<asp:ListItem Value="~/MasterPages/Title.master">Мастер-страница с баннером
</asp:ListItem>
<asp:ListItem Value="~/MasterPages/Title1.master">Мастер-страница без баннера
</asp:ListItem>
</asp:DropDownList>
</asp:Content>
Листинг
31.57.
Окончательный код страницы SatelliteDynamic.aspx
-
Откройте
поочередно файлы SatelliteDynamic1.aspx, SatelliteDynamic2.aspx, SatelliteDynamic3.aspx , SatelliteDynamic4.aspx и
добавьте в каждый из них после директивы @Page такой
блок скриптов
<script runat="server">
protected void Page_PreInit(object sender, EventArgs e)
{
if (Session["Master"] != null)
{
// Был ранее сохраненный выбор, включить его
Page.MasterPageFile = (string)Session["Master"];
}
}
</script>
Листинг
31.58.
Скрипты остальных контекстных страниц для загрузки выбранного шаблона
-
Исполните
начальную страницу SatelliteDynamic.aspx и
убедитесь, что мы дали пользователю полнофункциональный
механизм выбора шаблонов форматирования
Упражнение 17. Многослойное подключение мастер-страниц
Принципиально возможно подключение одной мастер-страницы к другой, система ASP.NET это позволяет. Можно использовать столько уровней вложения мастер-страниц, сколько это необходимо. Но нужно иметь ввиду, что многокаскадная схема подключения шаблонов делает код запутанным и ненадежным, поэтому рекомендуется использовать только один уровень мастер-страниц.
Но мы, все-таки, рассмотрим эту возможность на примере мастер-страниц двух уровней. Мы создадим две мастер-страницы с последовательным подключением нижнего уровня Level1 к верхнему Level0.
-
Код
страницы сделайте таким
<%@ 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; color: #0000ff">
<h1>
Мастер-страница уровня Level1 - наибольшей глубины.
Ее можно использовать как верхний колонтитул
</h1>
<asp:ContentPlaceHolder ID="ContentPlaceHolderLevel1" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Листинг
31.59.
Дескрипторный код страницы MasterPageLevel1.master
-
Теперь
также в корне Web-дерева создайте мастер-страницу
верхнего уровня с именем MasterPageLevel0.master и
подключите к ней предыдущую через атрибут MasterPageFile директивы @Master
Код страницы должен выглядеть так
<%@ Master Language="C#" MasterPageFile="~/MasterPageLevel1.master" %>
<asp:Content ID="ContentLevel0" ContentPlaceHolderID="ContentPlaceHolderLevel1" runat="server">
<table style="background-color: #ccff00" border="1">
<tr>
<td colspan="2">
<h2>
Мастер-страница уровня Level0 - верхнего уровня
</h2>
</td>
</tr>
<tr>
<td style="width: 200px">
<strong>Здесь можно расположить элементы навигации</strong>
</td>
<td style="background-color: #ccffff">
<asp:ContentPlaceHolder ID="ContentPlaceHolderLevel0" runat="server">
</asp:ContentPlaceHolder>
</td>
</tr>
</table>
</asp:Content>
Листинг
31.60.
Дескрипторный код страницы MasterPageLevel0.master
Обратите внимание, что при попытке переключить созданную мастер-страницу в режим Design оболочка выдает предупреждение
Это значит, что автоматизированный графический режим Design работает только для мастер-страницы верхнего уровня, а для уровней мастер-страниц большей глубины дескрипторный код нужно будет писать вручную в режиме Source.
-
Выполните
для страницы MasterPageLevel0.master команду Website/Add Content Page, чтобы
создать для нее контекстную страницу -
Измените
имя по умолчанию Default.aspx созданной
контекстной страницы на TestMasterPageLevel.aspx и
отредактируйте ее так
<%@ Page Language="C#" MasterPageFile="~/MasterPageLevel0.master" Title="Untitled Page" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolderLevel0" runat="Server">
<strong>Это есть заменяющее содержимое для мастер-страницы верхнего уровня Level0</strong>
</asp:Content>
Листинг
31.61.
Дескрипторный код страницы TestMasterPageLevel.aspx
-
Назначьте
контекстную страницу TestMasterPageLevel.aspx стартовой
и исполните ее
Результат будет таким
Итак, все работает, но нам это не надо - слишком запутано и посмотреть в Design нельзя!
Подключение мастер-страницы через конфигурационный файл
Для страниц, которые не имеют подключения мастер-страницы посредством атрибута MasterPageFile, можно задать мастер-страницу по умолчанию в кофигурационном файле блоком
<configuration>
<system.web>
<pages masterPageFile="XXX.master" />
</system.web>
</configuration>Этот подход не считается надежным, поскольку требует строгого согласования всех контекстных страниц с шаблонами одной мастер-страницы. Как только это условие будет нарушено, появится исключение. Если необходимо применить именно этот вариант, то нужно создать отдельную папку со своим файлом web.config и поместить в нее мастер-страницу и согласованные контекстные страницы.





