Файлы к лабораторной работе Вы можете скачать здесь.
Единообразие в оформлении множества отдельных страниц сайта является важной его характеристикой. Visual Studio 2005 имеет три возможности для поддержки стилевого оформления (форматирования) сайта:
Каскадными таблицы называют потому, что каждая из них реализует
принцип: стиль внутреннего каскада перекрывает действие стилей
всех внешних каскадов. Это устоявшееся средство стилевого оформления,
которое входит в HTML4 и
поддерживается практически всеми броузерами.
<head> и
имеет описание стилей общее для тех дескрипторов страницы,
на которые она должна действовать. Это индивидуальная настройка
стилей для страницы и бластью их действия являются теги только
одного документаПо отношению к этим трем типам CSS также соблюдается свойство каскадности, т.е. стиль внутреннего каскада имеет более высокий приоритет и перекрывает действие внешнего стиля.
Кратко рассмотрим все перечисленные типы CSS и их поддержку оболочкой Visual Studio 2005.
Стиль отдельного дескриптора определяется атрибутом style.
Синтаксис применения внутреннего стиля на примере дескриптора <h1> будет
таким

Значением стилевого атрибута является строка, представляющая
пары ' стиль:значение ', отделенные друг от
друга разделителем 'точка с запятой' или пробелом. Определенный
в дескрипторе внутренний стиль будет действовать только на
свой дескриптор и перекрывать все определения внешних стилей.
Командой
главного меню оболочки File/New/Website создайте новый пустой проект
с именем PageStyles
Командой
главного меню оболочки Website/Add New Item добавьте
в корневой узел проекта 
Запустите
утилиту WAT (Web Site
В открывшемся
окне броузера на странице WAT перейдите
на вкладку Application, щелкните на ссылке Configure debugging and tracing и в появившейся
странице включите флажок Enable debuggingВыполненное действие установит в debug в значение true.
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<appSettings/>
<connectionStrings/>
<system.web>
<compilation debug="true" />
<authentication mode="Windows" />
</system.web>
</configuration>
Добавьте
к проекту 
Поместите
внутрь дескриптора <body>
заголовочный дескриптор с внутренними стилевыми настройками,
дескриптор горизонтальной линии и ссылку на следующую страницу<h1 style="color: red; text-align: center">
Этот заголовочный текст будет центрирован в
сгенерированном документе и иметь красный цвет!
</h1>
<hr />
<a href=Page2.htm>Вперед</a>
Запустите
текущую страницу и убедитесь, что внутренний стиль дескриптора
действует
Определение внутренних стилей отдельных дескрипторов используется
редко. Чаще применяются встроенные стили, которые действуют
в пределах всей страницы. Встроенные стили не разбросаны по
странице, а размещаются внутри дескрипторного блока <head>...</head> в
специальном стилевом контейнере <style>...</style>.
Синтаксис встроенных стилей следующий

Атрибут type="text/css" дескриптора
стиля указывает броузеру, что ниже перечислены стили, которые
нужно применить к тексту при его отображении. Внутри стилевого
блока описываются именованные группы пар 'стиль:значение' с
разделителем 'точка с запятой', которые называются селекторами.
Имена селекторов могут совпадать с именами дескрипторов, например,
в приведенном выше примере селекторы body и h1 совпадают
с именами дескрипторов HTML. В этом случае дополнительных
указаний внутри дескрипторов не требуется.
Если используется список селекторов с определенными идентификаторами, то описанный в списке стиль применяется к элементам страницы с указанными идентификаторами и дополнительных указаний внутри именованных дескрипторов не требуется.
В качестве универсальных меток стилей могут использоваться
селекторы классов " .имя_класса ". Тогда в тех дескрипторах документа,
где необходимо применить определенный в классе стиль, должен
присутствовать атрибут class=" имя_класса".
Классы для конкретного вида тегов " тег.имя_класса " используются
только в тегах заданного типа по той же самой схеме class=" имя_класса".
Имена классов " .имя_класса " выбираются
произвольно.
Элементы списка селекторов отделяются друг от друга запятыми или пробелами. Если в определение одного свойства подразумевается много значений, то они также разделяются запятыми или пробелами. Если одно значение правила состоит из нескольких частей, разделенных пробелами, то оно обязательно заключается в двойные или одинарные кавычки.
В панели Solution Explorer вызовите контекстное меню
для корневого узла проекта и командой New Folder добавьте
папку с именем Resources
В панели Solution Explorer вызовите контекстное меню
для узла Resources и командой Add Existing Item скопируйте
в папку Resources из прилагаемого к работе
каталога Source файлы BackgroundImage.bmp и Web.jpg
Добавьте
к проекту <html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Документ со встроенной CSS</title>
<meta content="text/html; charset=windows-1251" http-equiv="Content-Type">
<style type="text/css">
body
{
background:url(Resources/Web.jpg);
font-family:Arial, Helvetica, sans-serif;
}
h1
{
color:#FF0000;
text-align:center;
}
#TextBox1
{
font-family:"Courier New", Courier, mono;
font-size:24px;
font:bold italic;
background-color:#0000FF;
color:yellow;
width:400;
}
.btnResult
{
background-image:url(Resources/BackgroundImage.bmp);
color:white;
}
</style>
</head>
<body>
<h1>
Заполните анкету!
</h1>
<form id="form1" action="Page2.htm">
<p>
Введите ФИО:
<input id="TextBox1" name="TextBox1" type="text">
</p>
<p>
Введите ИНН:
<input id="TextBox2" name="TextBox2" type="text">
</p>
<center>
<input id="Button1" class="btnResult" name="Button1"
type="button" value="Отослать">
</center>
</form>
</body>
</html>
Запустите
страницу Page2.htm и проверьте результат
Внешними считаются стили, которые хранятся в отдельном файле
<style></style><head>...</head> дескриптора <link> или
директивы @impotПусть имеется два файла с внешними стилями и произвольными
именами, например, header.css и default.css.
Варианты их подключения в HTML-документ Page3.htm ( обязательно в
заголовочный блок <head>...</head> )
приведены в таблице:
| Вариант | В блоке <head> файла Page3.htm |
Замечания |
|---|---|---|
| Подключается одна CSS | <link rel="stylesheet" href="header.css"> |
|
| Подключается две CSS | <link rel="stylesheet" href="header.css"> <link rel="stylesheet" href="default.css"> |
|
| Подключается одна CSS | <style type="text/css"> @import url(header.css); </style> |
Не поддерживается |
| Подключается две CSS | <style type="text/css"> @import url(header.css); @import url(default.css); </style> |
Не поддерживается |
| Подключается две CSS ( в страницу импортируется цепочка CSS) | <style type="text/css"> @import url(header.css); </style> |
В самом начале файла header.css имеется голая строка
прямого подключения: |
| Подключается две CSS | <style type="text/css"> @import url(header.css); </style> <link rel="stylesheet" href="default.css"> |
Порядок следования не влияет |
| Подключается две CSS | <link rel="stylesheet" href="default.css"> <style type="text/css"> @import url(header.css); </style> |
Порядок следования не влияет |
| Подключается три CSS | <link href="default.css" rel="stylesheet">
<style type="text/css">
@import url(header.css);
body
{
background:white url(Web.jpg);
font-family:Arial, Helvetica, sans-serif;
}
h1
{
color:#FF0000;
text-align:center;
}
#TextBox1
{
font-family:"Courier New", Courier, mono;
font-size:24px;
font:bold italic;
background-color:#0000FF;
color:yellow;
width:400;
}
.btnResult
{
background-image:url(BackgroundImage.bmp);
color:white;
}
</style>
|
Подключается две внешних таблицы в дополнение к встроенной. Встроенные стили теоретически должны иметь выше приоритет, чем внешние. Но это зависит от конкретного броузера. Поэтому, чтобы избежать недоразумений, одновременно применять внешние и встроенные таблицы стилей не следует. Порядок следования не влияет |
| Подключается три CSS | <style type="text/css">
body
{
background:white url(Web.jpg);
font-family:Arial, Helvetica, sans-serif;
}
h1
{
color:#FF0000;
text-align:center;
}
#TextBox1
{
font-family:"Courier New", Courier, mono;
font-size:24px;
font:bold italic;
background-color:#0000FF;
color:yellow;
width:400;
}
.btnResult
{
background-image:url(BackgroundImage.bmp);
color:white;
}
@import url(header.css);
</style>
<link href="default.css" rel="stylesheet">
|
Подключается две внешних таблицы в дополнение к встроенной. Встроенные стили теоретически должны иметь выше приоритет, чем внешние. Но это зависит от конкретного броузера. Поэтому, чтобы избежать недоразумений, одновременно применять внешние и встроенные таблицы стилей не следует. Порядок следования не влияет |
Применим рассмотренный материал на практике.
В панели Solution Explorer найдите страницу Page2.htm и
сделайте из нее две копии с именами Page3.htm и ExternalCSS.css
Откройте файл Page3.htm и
замените в заголовке <head> встроенный
стиль на строку подключения внешней каскадной таблицы
стилей<link rel="stylesheet" href=" ExternalCSS.css">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Документ со встроенной CSS</title>
<meta content="text/html; charset=windows-1251" http-equiv="Content-Type">
<link href="ExternalCSS.css" rel="stylesheet">
</head>
<body>
<h1>
Заполните анкету!
</h1>
<form id="form1" action="Page3.htm">
<p>
Введите ФИО:
<input id="TextBox1" name="TextBox1" type="text">
</p>
<p>
Введите ИНН:
<input id="TextBox2" name="TextBox2" type="text">
</p>
<center>
<input id="Button1" class="btnResult" name="Button1"
type="button" value="Отослать">
</center>
</form>
</body>
</html>
Откройте файл ExternalCSS.css и
оставьте только чистый код селекторов и определений стилейbody
{
background:url(Resources/Web.jpg);
font-family:Arial, Helvetica, sans-serif;
}
h1
{
color:#FF0000;
text-align:center;
}
#TextBox1
{
font-family:"Courier New", Courier, mono;
font-size:24px;
font:bold italic;
background-color:#0000FF;
color:yellow;
width:400;
}
.btnResult
{
background-image:url(Resources/BackgroundImage.bmp);
color:white;
}
Откройте
страницу Page3.htm в броузере и убедитесь,
что получился тот же результат, что и при использовании
встроенных стилей в странице Page2.htm
Опробуйте
другие варианты подключения внешней CSS,
приведенные ранее в таблицеИтак, внешняя CSS, это обычный текстовый файл, которому традиционно назначают расширение .css для лучшей узнаваемости, хотя может использоваться любое другое расширение. Его можно создавать отдельно в любом текстовом редакторе, а затем использовать в Web-проекте. Но Visual Studio 2005 имеет свои встроенные средства создания CSS. Рассмотрим их.
Добавьте
в корневой узел сайта командой Website/Add New Item новый
файл типа Style Sheet с
именем StyleSheet.css (по
умолчанию)
Оболочка добавит в проект новый файл
Наша главная задача, как программистов, - понимать и правильно применять CSS, а на чем она подготовлена или кем (пусть у дизайнеров голова болит), не очень важно. Но если приспичит, можно порекомендовать специализированный редактор CSS, который позволяет кодировать вручную или использовать удобный интерфейс. Это редактор StyleMaster, информацию о котором можно найти в Internet по ссылке www.westciv.com/style_master
Не будем использовать созданную оболочкой заготовку StyleSheet.css,
а научимся подключать к
странице через оболочку свою уже готовую
Удалите
созданную оболочкой заготовку StyleSheet.css
Создайте
копию статической страницы Page3.htm и
присвойте копии имя Page4.htm
Назначьте
страницу Page4.htm стартовой (команда Set
As Start Page ) и запустите ее на выполнение, чтобы
убедиться в ее работоспособностиЕсли страница не содержит серверных элементов с атрибутом runat="server", то система ASP.NET
просто отсылает клиенту код этой страницы в неизменном
виде. Если посмотреть на исходный HTML-код присланной броузеру
страницы (команда View
Source контекстного
меню окна броузера), то он остался тем же самым, что и в генерирующей
странице Page4.htm
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Документ со встроенной CSS</title>
<meta content="text/html; charset=windows-1251" http-equiv="Content-Type">
<link href="ExternalCSS.css" rel="stylesheet">
</head>
<body>
<h1>
Заполните анкету!
</h1>
<form id="form1" action="Page3.htm">
<p>
Введите ФИО:
<input id="TextBox1" name="TextBox1" type="text">
</p>
<p>
Введите ИНН:
<input id="TextBox2" name="TextBox2" type="text">
</p>
<center>
<input id="Button1" class="btnResult" name="Button1"
type="button" value="Отослать">
</center>
</form>
</body>
</html>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Документ со встроенной CSS</title>
<meta content="text/html; charset=windows-1251" http-equiv="Content-Type">
<link href="ExternalCSS.css" rel="stylesheet">
</head>
<body>
<h1>
Заполните анкету!
</h1>
<form id="form1" action="Page4.htm">
<p>
Введите ФИО:
<input id="TextBox1" name="TextBox1" type="text">
</p>
<p>
Введите ИНН:
<input id="TextBox2" name="TextBox2" type="text">
</p>
<center>
<input id="Button1" class="btnResult" name="Button1"
type="button" value="Отослать">
</center>
</form>
</body>
</html>
Отвлечемся немного от темы стилей и обратим внимание на то, сколько строк нашего кода возможно подчеркнул редактор оболочки красной линией. Это значит, что его не устраивает синтаксис кода, на проверку которого он настроен.

Чтобы успокоить редактор, нужно сообщить ему, чтобы он проверял синтакис чистого HTML, а не XHTML.
Выполните
команду Tools/Customize и отметьте флажок HTML Source Editing
В верхней части каркаса оболочки появится панель инструментов
настройки HTML-редактора, в которой нужно установить через
раскрывающийся список опцию HTML
4.01. Через некоторое время,
после очередного сканирования синтаксиса документа <form>.
Чтобы избавиться и от этого замечания редактора, нужно добавить
атрибут action с целевой страницей, которая
будет обрабатывать обратную отсылку (постинг) на сервер, в нашем
случае
<form action="Page4.htm">
Посмотрите, как и в этом случае нам услужливо помогает подсказчик
кода , предлагающий выбрать
из списка файлов целевую страницу на сервере, которая будет принимать
данные от формы

Вообще-то, большинство броузеров при пропущенном атрибуте action полагают,
что целевой будет та же самая страница.
Но чтобы успокоить HTML редактор окончательно, укажем эту страницу
явно.
Вызовите
контекстное меню щелчком правой кнопки мыши на свободном
месте верхней части каркаса оболочки и сбросьте флажок HTML
Source Editing, чтобы закрыть одноименную панель
настройки редактора
Удалите
из заголовочного блока страницы Page4.htm код
подключения внешней <link rel="stylesheet" href="ExternalCSS.css">
Переведите
страницу в режим Design и посмотрите, какая
она сразу стала некрасивая
Вернитесь
в режим Source и убедитесь, что оболочка
добавила нужный дескриптор подключения CSS в
нужное место
Опять
удалите дескриптор подключения CSS
Перейдите
в режим Design, откройте панель Properties и
через раскрывающийся список в ее верхней части выберите объект DOCUMENT
Найдите
свойство StyleSheet и подключите к нему
таблицу ExternalCSS.css через диалоговое
окно. Оболочка опять добавит нужный дескриптор подключения CSS в
нужное место
Очистите
поле свойства StyleSheet, оболочка вновь
удалит дескриптор подключенияТаблицы CSS применяются не только к простым
дескрипторам HTML,
но и к дескрипторам Label.
Откройте
панель ToolboxМы видим, что доступной является только вкладка HTML, потому, что наша тестовая страница Page4.htm имеет расширение .htm.
Измените
в панели Solution Explorer расширение страницы
на Page4.aspx и
сделайте страницу принимающей, исправив дескриптор <form><form action="Page4.aspx"
runat="server">
Вкладка Standard в панели Toolbox все равно не появилась, потому что редактор оболочки все еще считает страницу статической.
Для
изменения мнения редактора о типе страницы закройте редактирование
страницы Page4.aspx, затем вновь откройте
Поместите
на страницу между текстовым
полем и кнопкой из вкладки Standard текстовую
метку Label и
в панели Properties определитеCssClass=labelText=Стиль
класса label
Откройте
через Solution Explorer файл ExternalCSS.css и
добавьте стилевое правило для класса label .label
{
background-color:Green;
color:White;
font:bold;
font-size:x-large;
font-family:Courier New;
}
body
{
background:white url(Web.jpg);
font-family:Arial, Helvetica, sans-serif;
}
h1
{
color:#FF0000;
text-align:center;
}
#TextBox1
{
font-family:"Courier New", Courier, mono;
font-size:24px;
font:bold italic;
background-color:#0000FF;
color:yellow;
width:400;
}
.btnResult
{
background-image:url(BackgroundImage.bmp);
color:white;
}
Переведите
страницу в режим Design,
Выполните
страницу, которая
в броузере станет такой
Краткое знакомство с CSS и их поддержкой в Visual Studio 2005 закончили!
Применение CSS для стилевого оформления страниц ASP.NET имеет некоторые ограничения. Дело в том, что CSS являются решением стороны броузера. Они оформляют уже готовые дескрипторы HTML, поступившие на броузер. Если их бездумно применять на стороне сервера к элементам управления, которые могут генерировать для отправки клиенту целый пакет HTML-дескрипторов, то конечное стилевое оформление может не в полной мере соответствовать желаниям разработчика. Для таких ситуаций существуют другие средства форматирования, которые являются родным решением элементов управления на стороне сервера и позволяют полностью контролировать их стилевое оформление. Одним из таких средств являются темы.
Как и CSS, темы определяют набор стилей, которые называют оформлениями и которые можно применять на многих страницах ASP.NET. Особенности тем состоят в следующем:
http://
www.asp.net. Но если тема используется, то
для обеспечения гибкости и автономности она должна физически
находиться в каталоге приложения.Все темы помещаются в каталог с зарезервированным именем App_Themes,
который можно добавить к приложению в панели Solution
Explorer,
выполнив команду Add ASP.NET Folder/Theme контекстного
меню для узла приложения
Каждая тема должна храниться в своей одноименной папке и может
состоять из нескольких файлов

Папку App_Themes отдельно можно и не создавать, потому, что при попытке добавления нового файла типа Skin File оболочка предложит автоматически создать папку App_Themes

Для темы можно все стилевые настройки элементов управления разместить в одном файле оформленийscin, а можно и в нескольких. Иногда просто удобнее группировать оформления по отдельным категориям элементов управления в соответствующих файлах. Для ASP.NET это не имеет никакого значения, поскольку она все равно считывает все файлы оформлений в каталоге указанной темы как неделимое целое определения одной темы.
Структура папки App_Themes может иметь следующий вид

Проверим сказанное на практике.
Добавьте
к проекту новую страницу Page5.aspx с
отделенным кодом
Добавьте
на страницу из вкладки Standard следующие
элементы управленияBulletedListLabelCheckBox Button
Назначьте
свойства Text этих элементов (для BulletedList - коллекция Items ) и
скомпонуйте их на странице так, чтобы их внешний вид
на этапе проектирования был следующим
В панели Solution Explorer создайте копию файла Page5.aspx и
присвойте ей имя FirstSkin.aspx.
Из него мы в дальнейшем сделаем файл оформлений
Удалите
файл кодовой поддержки FirstSkin.aspx.cs
Настройте
декларативно в панели Properties стилевые свойства объектов
страницы FirstSkin.aspx| Элемент | Свойство | Значение |
|---|---|---|
BulletedList |
ID |
BulletedList1 |
|
BackColor |
Yellow |
|
BorderColor |
Red |
|
BorderStyle |
|
|
|
10px |
|
BulletStyle |
Numbered |
|
ForeColor |
Blue |
Label |
ID |
Label1 |
|
BackColor |
Blue |
|
ForeColor |
Yellow |
|
|
Текстовая метка |
|
ID |
CheckBox1 |
|
BackColor |
Red |
|
BorderStyle |
|
|
Font/Bold |
True |
|
ForeColor |
White |
Button |
ID |
Button1 |
|
BackColor |
#FFC0C0 |
|
BorderColor |
Blue |
|
BorderStyle |
|
|
|
2px |
|
Font/Bold |
True |
|
ForeColor |
Blue |
Внешний вид элементов управления после проведенных стилевых настроек должен быть таким

Перейдите
в режим Source и удалите из файла FirstSkin.aspx весь
код, кроме открывающих дескрипторов элементов управления, в
которых тоже удалите атрибуты, не относящиеся к настройкам
стиля, включая атрибут IDВ файле FirstSkin.aspx должно остаться следующее
<asp:BulletedList runat="server"
BackColor="Yellow" BorderColor="Red"
BorderStyle="Ridge" BorderWidth="10px"
BulletStyle="Numbered" ForeColor="Blue" />
<asp:Label runat="server"
BackColor="Blue" ForeColor="Yellow"
ToolTip="Текстовая метка" />
<asp:CheckBox runat="server"
BackColor="Red" BorderStyle="Groove"
Font-Bold="True" ForeColor="White" />
<asp:Button runat="server"
BackColor="#FFC0C0" BorderColor="Blue"
BorderStyle="Solid" BorderWidth="2px"
Font-Bold="True" ForeColor="Blue" />
Присвойте
файлу FirstSkin.aspx новое расширение FirstSkin.skin
Создайте
в приложении папку с зарезервированным именем App_Themes и
определите в ней подпапку с именем MyTheme,
в которой будут храниться файлы оформлений этого
упражнения (точнее, будет всего один файл FirstSkin.skin )
В панели Solution
Explorer Тема подключается к странице с помощью атрибута директивы @Page. Так, например, при применении темы
с именем каталога MyTheme к странице упражнения Page5.aspx директива
будет выглядеть так
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="Page5.aspx.cs" Inherits="Page5"
Theme="MyTheme" %>
Тему можно подключить к странице и в панели Properties через
свойство объекта DOCUMENT.
В этом случае оболочка автоматически добавит атрибут к
директиве @Page с выбранным значением.
В раскрывающемся
списке панели Properties для
страницы Page5.aspx выделите объект DOCUMENT и
установите свойство Theme ="MyTheme"
Назначьте
страницу Page5.aspx стартовой и выполните
ееПредставление рендеринга на стороне клиента, сгенерированного активной страницей Page5.aspx, с учетом присоединенных через тему стилевых настроек элементов управления будет иметь вид

Естественно, что переопределяются только те стилевые настройки элементов управления страницы, которые указаны в подключенной теме. Остальные настройки не переопределяются.
При подключении CSS стили
начинают действовать на отображение элементов немедленно, на
этапе проектирования и мы можем их подбирать, сразу видя результат.
При определении свойства действие
стилей мы увидим только на этапе выполнения. Механизм тем реализует
стилевые способности генерирующих элементов управления только
при выполнении в соответствии с настройками, хранящимися отдельно
в одном или нескольких файлах оформлений каталога темы.
Элементы управления страницы могут иметь свои индивидуальные стилевые настройки, которые мы им декларативно назначим при разработке страницы. Но если элемент на странице имеет настройки, которые дублируются в теме, то приоритет будут иметь одноименные настройки, указанные в подключаемой теме. Проверим это...
В панели Solution Explorer получите копию страницы Page5.aspx и
присвойте ей имя Page6.aspx
Установите
прямо в настройках страницы Page6.aspx для
элемента CheckBox1 атрибутыBackColor="Black"ForeColor="Yellow"Мы хотим,
чтобы элемент CheckBox1 имел черный фон
и желтый текст, т.е. ждем его таким

Выполните
страницу и убедитесь, что элемент CheckBox1 попрежнему
будет иметь цвет фона красный, а Theme ="MyTheme" Объект DOCUMENT страницы
имеет еще одно свойство StyleSheetTheme, к
которому также можно подключить внешнюю тему. В этом случае
приоритет будут иметь индивидуальные настройки элементов управления,
которые в них были явно определены. Но те настройки по умолчанию,
которые мы не определяли на странице, но которые содержатся
в теме, на свойства по умолчанию действуют.

Для
страницы Page6.aspx в панели Properties выделите
объект DOCUMENT, очистите поле его свойства Theme и
подключите тему MyTheme к свойству StyleSheetTheme
Выполните
страницу и убедитесь, что индивидуальная настройка элемента CheckBox1 имеет
приоритетEnableTheming="False".
Влияние настроек темы на всю страницу можно отключить,
если в директиве @Page страницы установить
атрибут EnableTheming="False" (по
умолчанию это свойство страницы имеет значение True ).
Для
страницы Page6.aspx в панели Properties выделите объект DOCUMENT,
очистите поле его свойства StyleSheetTheme и
подключите тему MyTheme к свойству Theme
Выделите
объект CheckBox1 с индивидуальными настройками BackColor="Black" ; ForeColor="Yellow" и
отключите для него влияние темы EnableTheming="False"
Выполните
страницу и убедитесь, что настройки темы отключены и действуют
только настройки по умолчанию и индивидуальные настройки
элемента
Выделите
объект CheckBox1 и верните
для него EnableTheming="True"Стилевые настройки, которые мы до сих пор определяли в файле оформлений темы, являются настройками
по умолчанию и
применяются для всех элементов управления
Если просто определить в теме несколько
вариантов настроек для одного и того же элемента управления,
то ASP.NET выдаст ошибку об обнаружении неоднозначности.
В этом случае в теме нужно применять именованные
оформления с помощью атрибута SkinID. Стиль элемента управления в файле
оформлений будет иметь метку SkinID, и на странице наряду
с общим подключением темы с помощью свойства нужно
будет определить дополнительные свойства SkinID для
отдельных элементов управления.
Значения SkinID в определениях темы должно
быть уникальным только в группе однотипных элементов. Это значит,
что мы можем создать несколько групп настроек разнотипных элементов
с одинаковыми значениями атрибута SkinID и
подключать из одной темы, по мере необходимости, к каждому
элементу управления свои индивидуальные настройки.
Скопируйте
страницу Page5.aspx в страницу Page7.aspx
Добавьте
в страницу Page7.aspx элемент Table из
вкладки HTML панели Toolbox. Таблицу расположите между кнопкой
и Для нашего упражнения таблица должна иметь три столбца и пять строк. Оболочка не обладает развитыми средствами редактирования таблиц, поэтому проще настроить таблицу в режиме Source.
Поместите
из вкладки Standard панели Toolbox в
средний столбец таблицы пять серверных элементов Label,
а в правый - пять серверных элементов CheckBox SkinID не подключен: действуют общие настройки
по умолчанию |
Label2 |
![]() |
Именованные настройки подключены: SkinID="Variant3" |
Label3 |
![]() |
Именованные настройки подключены: SkinID="Variant4" |
Label4 |
![]() |
SkinID="Variant5" подключен, но тема подавлена: EnableTheming="False" |
Label5 |
![]() |
Подключен несуществующий SkinID="XXX": настройки темы
не действуют |
Label6 |
![]() |
В панели Solution Explorer щелкните на узле MyTheme и
добавьте к проекту новый файл оформлений с именем FirstSkinID.skin 
Очистите
от комментариев файл
оформленийFirstSkinID.skin и
дополните его индивидуальными именованными настройками
стилей, чтобы общий код его стал таким<asp:Label runat="server" BackColor="Blue" ForeColor="Yellow" SkinID="Variant2" />
<asp:CheckBox runat="server" BackColor="Red" BorderStyle="Groove"
Font-Bold="True" ForeColor="White" SkinID="Variant2" />
<asp:Label runat="server" ForeColor="Blue" SkinID="Variant3" />
<asp:CheckBox runat="server" BorderStyle="Dotted" Font-Bold="True"
ForeColor="Red" SkinID="Variant3" />
<asp:Label runat="server" BackColor="Yellow" ForeColor="Red" SkinID="Variant4" />
<asp:CheckBox runat="server" BackColor="Red" BorderStyle="Solid"
ForeColor="Yellow" SkinID="Variant4" />
<asp:Label runat="server" BackColor="Blue" ForeColor="Yellow" SkinID="Variant5" />
<asp:CheckBox runat="server" BackColor="Red" BorderStyle="Groove"
Font-Bold="True" ForeColor="White" SkinID="Variant5" />
<asp:Label runat="server" BackColor="Blue" ForeColor="Yellow" SkinID="Variant6" />
<asp:CheckBox runat="server" BackColor="Red" BorderStyle="Groove"
Font-Bold="True" ForeColor="White" SkinID="Variant6" />
Установите
в добавленных объектах свойство SkinID в
соответствии с первым столбцом компоновочной таблицы, приведенной
ранее
Выполните
страницу Page7.aspx, результат должен быть примерно таким
Вспомним, что активизируются все файлы оформлений, соответствующие указанной теме и расположенные в соответствующем одноименном каталоге. И в нашем упражнении часть элементов страницы оформляется с помощью неименованных атрибутов, расположенных в файле App_Themes\MyTheme\ FirstSkin.skin, а часть - с помощью именованных, расположенных в файле App_Themes\MyTheme\ FirstSkinID.skin.
Можно сделать все стилевые оформления именованными.
В этом случае, если в элементах управления на странице не
будет задан атрибут SkinID,
то эти именованные стилевые настройки никогда не будут применяться.
Окончательный код интерфейсной части страницы Page7.aspx будет следующим
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="Page7.aspx.cs" Inherits="Page7"
Theme="MyTheme" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:BulletedList ID="BulletedList1" runat="server">
<asp:ListItem>Туризм</asp:ListItem>
<asp:ListItem>Спорт</asp:ListItem>
<asp:ListItem>Музыка</asp:ListItem>
<asp:ListItem Value="Танцы"></asp:ListItem>
</asp:BulletedList>
<asp:Label ID="Label1" runat="server" Text="Текстовая метка"></asp:Label>
<asp:CheckBox ID="CheckBox1" runat="server" Text="Флажок" />
<br />
<br />
<table bgcolor="#FFFFFF">
<tr>
<td>
SkinID не подключен: действуют общие настройки по умолчанию
</td>
<td>
<asp:Label ID="Label2" runat="server" Text="Label2"></asp:Label></td>
<td style="height: 26px">
<asp:CheckBox ID="CheckBox2" runat="server" Text="CheckBox2" /></td>
</tr>
<tr>
<td>
Именованные настройки подключены: SkinID="Variant3"</td>
<td>
<asp:Label ID="Label3" runat="server" SkinID="Variant3" Text="Label3"></asp:Label></td>
<td>
<asp:CheckBox ID="CheckBox3" runat="server" SkinID="Variant3" Text="CheckBox3" /></td>
</tr>
<tr>
<td>
Именованные настройки подключены: SkinID="Variant4"</td>
<td>
<asp:Label ID="Label4" runat="server" SkinID="Variant4" Text="Label4"></asp:Label></td>
<td>
<asp:CheckBox ID="CheckBox4" runat="server" SkinID="Variant4" Text="CheckBox4" /></td>
</tr>
<tr>
<td>
SkinID="Variant5" подключен, но тема подавлена: EnableTheming="False"</td>
<td>
<asp:Label ID="Label5" runat="server" EnableTheming="False" SkinID="Variant5"
Text="Label5"></asp:Label></td>
<td>
<asp:CheckBox ID="CheckBox5" runat="server" EnableTheming="False" SkinID="Variant5"
Text="CheckBox5" /></td>
</tr>
<tr>
<td>
Подключен несуществующий SkinID="XXX": настройки темы не действуют</td>
<td>
<asp:Label ID="Label6" runat="server" SkinID="XXX" Text="Label6"></asp:Label></td>
<td>
<asp:CheckBox ID="CheckBox6" runat="server" SkinID="XXX" Text="CheckBox6" /></td>
</tr>
</table>
<br />
<asp:Button ID="Button1" runat="server" Text="Отправить" />
</div>
</form>
</body>
</html>
Сложные элементы управления включают в себя несколько разделов, требующих индивидуальных стилевых оформлений. Эти настройки могут занимать много места, если их использовать вместе с дескрипторным кодом в интерфейсной части страницы. Поэтому для таких элементов выносить громоздкий код стилевых настроек в отдельный файл оформлений очень даже удобно. Приведем пример с настройками элемента Calendar.
Создайте
новую страницу со встроенным кодом поддержки и с именем Page8.aspx
Назначьте
страницу стартовой и поместите на нее из вкладки Standard элемент
управления Calendar
Определите
для объекта Calendar1 следующие стилевые
настройки<asp:Calendar ID="Calendar1" runat="server"
BackColor="white" ForeColor="black" BorderColor="black"
BorderStyle="solid" CellSpacing="1" Font-Names="Vernada"
Font-Size="9pt" Height="250px" Width="500px"
NextPrevFormat="ShortMonth" SelectionMode="day">
<SelectedDayStyle BackColor="darkorange" ForeColor="white" />
<DayStyle BackColor="orange" Font-Bold="true" ForeColor="white" />
<NextPrevStyle Font-Bold="true" Font-Size="8pt" ForeColor="white" />
<DayHeaderStyle Font-Bold="true" Font-Size="8pt"
ForeColor="#333333" Height="8pt" />
<TitleStyle BackColor="firebrick" BorderStyle="none"
Font-Bold="true" Font-Size="12pt"
ForeColor="white" Height="12pt" />
<OtherMonthDayStyle BackColor="navajowhite"
Font-Bold="false" ForeColor="darkgray" />
</asp:Calendar>
В панели Solution Explorer вызовите контекстное меню
для папки MyTheme и командой Add
New Item создайте новый файл оформлений с
именем Calendar.skin
Запомните,
как пишутся комментарии в интерфейсных файлах ASP.NET и
очистите автоматически сгенерированный текст в файле
оформленийCalendar.skin
Скопируйте
из страницы Page8.aspx в файл оформленийCalendar.skin весь
дескрипторный код объекта Calendar1 вместе
с его стилевыми настройками и
удалите в копии атрибут ID="Calendar1",
оставив только атрибуты стилевых настроек<asp:Calendar runat="server"
BackColor="white" ForeColor="black" BorderColor="black"
BorderStyle="solid" CellSpacing="1" Font-Names="Vernada"
Font-Size="9pt" Height="250px" Width="500px"
NextPrevFormat="ShortMonth" SelectionMode="day" >
<SelectedDayStyle BackColor="darkorange" ForeColor="white" />
<DayStyle BackColor="orange" Font-Bold="true" ForeColor="white" />
<NextPrevStyle Font-Bold="true" Font-Size="8pt" ForeColor="white" />
<DayHeaderStyle Font-Bold="true" Font-Size="8pt" ForeColor="#333333" Height="8pt" />
<TitleStyle BackColor="firebrick" BorderStyle="none" Font-Bold="true"
Font-Size="12pt" ForeColor="white" Height="12pt" />
<OtherMonthDayStyle BackColor="navajowhite" Font-Bold="false" ForeColor="darkgray" />
</asp:Calendar>
Удалите
в дескрипторном коде страницы Page8.aspx код
стилевых настроек объекта Calendar1, чтобы
от объекта осталось только простое описание<asp:Calendar ID="Calendar1" runat="server">
</asp:Calendar>
Через
панель Properties выделите объект DOCUMENT и поключите
к странице тему MyTheme в свойстве Theme
Выполните
страницу и убедитесь, что вынесенный со страницы в тему большой
блок стилевых настроек элемента Calendar работает
также, как если бы он находился на самой страницеНиже приведены два варианта представления объекта Calendar1: без темы и с подключенной темой
![]() |
![]() |
| Тема с настройками не подключена | Внешние стилевые настройки работают |
|---|
С помощью внешних файлов оформлений и тем можно подключать
стилевые компоненты рисунков. Пусть мы хотим использовать несколько
кнопок элемента управления с разными
рисунками в зависимости от контекста применения. Пусть для
кнопок OK будет использован один рисунок,
а для кнопок - другой. Темы позволяют
легко решить эту задачу.
В
панели Solution Explorer через контекстное
меню на папке MyTheme командой New Folder создайте
подпапку ButtonImages для
хранения рисунков кнопок
В
панели Solution Explorer через контекстное
меню на новой папке ButtonImages командой Add Existing Item вызовите диалоговое окно
копирования и из прилагаемого каталога Source скопируйте
рисунки ButtonCancel.png и ButtonOK.png
Создайте
из страницы Page8.aspx копию с именем Page9.aspx и
назначьте ее стартовой
Добавьте
на страницу Page9.aspx из вкладки Standard панели Toolbox две
кнопки типа ImageButton и
настройте через одноименные свойства в панели Properties их
дескрипторы так<asp:ImageButton ID="ImageButton1" runat="server"
ImageUrl="~/App_Themes/MyTheme/ButtonImages/ButtonOK.png"
SkinID="OKButton" />
<asp:ImageButton ID="ImageButton2" runat="server"
ImageUrl="~/App_Themes/MyTheme/ButtonImages/ButtonCancel.png"
SkinID="CancelButton" />
В контекстном
меню на папке MyTheme выполните команду Add
New Item, чтобы добавить в тему новый файл оформленияButtons.skin
Скопируйте
настроенные дескрипторы элементов ImageButton в
файл Buttons.skin, предварительно очистив
его от автоматически сгенерированных инструкций
Удалите
из файла оформлений Buttons.skin атрибуты ID, чтобы код стал выглядеть так<asp:ImageButton runat="server"
ImageUrl="ButtonImages/ButtonOK.png"
SkinID="OKButton" />
<asp:ImageButton runat="server"
ImageUrl="ButtonImages/ButtonCancel.png"
SkinID="CancelButton" />
Обратите внимание, что мы в атрибуте ImageUrl указали
путь только относительно каталога темы. Путь до корня виртуального
каталога сайта " ~/App_Themes/MyTheme/ " добавит ASP.NET при компиляции этого кода и автоматически
преобразует его в абсолютный путь файловой системы сервера.
Откорректируйте
дескрипторы ImageButton в файле Page9.aspx,
чтобы от них осталось только следующее<asp:ImageButton ID="ImageButton1" runat="server" SkinID="OKButton" /> <asp:ImageButton ID="ImageButton2" runat="server" SkinID="CancelButton" />
Исполните
страницу Page9.aspx и получите следующий
результат с внешними оформлениями в темах сложного календаря
и рисуночных кнопок
На интерфейсной странице находится дескрипторный код только создания сложных элементов управления, а большой код тонких настроек вынесен в файлы темы. Это очень удобно и для централизованного изменения стилевого оформления элементов управления, и для читабельности самой страницы.
Если у нас имеются хорошие наработки CSS, то ASP.NET позволяет использовать их для форматирования HTML-дескрипторов активной страницы. Чтобы подключить CSS к активной странице, нужно сделать следующее:
CSS в каталог
темыTheme объекта DOCUMENT страницыCSS содержит классы, подключить
их в свойстве CssClass элементов
управления страницы<link>, используемого
при традиционном способе подключения к странице, проследить,
чтобы заголовочный дескриптор страницы был объявлен как серверный
( <head runat="server"> ).
В этом случае ASP.NET сама при запросах
страницы будет генерировать столько дескрипторов <link> в
выходном HTML-коде, сколько файлов CSS будет
находиться в подключенной к странице темеПроверим сказанное. В панели Solution Explorer оболочки выполните следующие действия:
Скопируйте
файл Page4.aspx, присвойте копии имя Page10.aspx и
назначьте новую страницу стартовой
Откройте
файл Page5.aspx, скопируйте из него на страницу Page10.aspx (ниже
кнопки) интерфейсный код BulletedList, Label, CheckBox После этого вид страницы Page10.aspx без стилевого оформления на этапе проектирования должен быть таким

Скопируйте таблицу
стилей ExternalCSS.css в
папку MyTheme проекта.
Копирование выполните в панели Solution Explorer так:
щелкните правой кнопкой мыши на файле ExternalCSS.css и
выполните команду Copy, затем щелкните правой
кнопкой мыши на папке MyTheme и выполните
команду Paste. Назначьте копии
имя ThemeCSS.css
Подобным
же образом скопируйте из каталога Resources в
каталог MyTheme два
файла BackgroundImage.bmp и Web.jpg,
чтобы они оказались в одном каталоге с файлом ThemeCSS.css
Откройте
страницу Page10.aspx на редактирование,
удалите в ней дескриптор <link> подключения
внешней <head> атрибут runat="server",
чтобы он стал обрабатываться средой ASP.NET
Откройте
файл ThemeCSS.css и замените
url( |
---> |
url(Web. |
url( |
---> |
url(BackgroundImage. |
Подключить
тему MyTheme к
странице Page10.aspx, добавив в самое ее
начало директиву<%@ Page Language="C#"
Выполните
страницу Page10.aspx и убедитесь, что
стили из внешней таблицы ThemeCSS.css работаютРезультат выполнения страницы будет таким

На данной странице Page10.aspx <link> ссылку
на внешнюю CSS.
Броузер, получив ссылку на внешнюю CSS,
проверяет в соответствии с правилом приоритета стилей возможность
их применения только в тех дескрипторах HTML, в которых
нет своих внутренних стилей, сгенерированных серовером на
основании темы.
Иными словами
Теперь осталось проверить тот факт, что ASP.NET подключает
к странице все
В каталоге Theme сделайте еще три копии файла ThemeCSS.css с
именем ThemeCSS1.css, ThemeCSS2.css, ThemeCSS3.css
Выполните
страницу Page10.aspx и в появившемся окне броузера выполните
команду контекстного меню View Source для
присланной с сервера страницы-откликаИсследуем блок кода заголовочного дескриптора <head>. Он будет содержать такие строки
<head>
<title>Документ с внешней CSS</title>
<meta content="text/html; charset=windows-1251" http-equiv="Content-Type" />
<link href="App_Themes/MyTheme/ThemeCSS.css" type="text/css" rel="stylesheet" />
<link href="App_Themes/MyTheme/ThemeCSS1.css" type="text/css" rel="stylesheet" />
<link href="App_Themes/MyTheme/ThemeCSS2.css" type="text/css" rel="stylesheet" />
<link href="App_Themes/MyTheme/ThemeCSS3.css" type="text/css" rel="stylesheet" />
</head>
Мы видим, что среда исполнения ASP.NET автоматически вставляет в код столько дескрипторов подключения CSS, сколько файлов с таблицами находится в каталоге темы. Обратите внимание, что пути в ссылках прописываются относительно корня виртуального каталога, в котором находится сама страница.
Удалите
лишние файлы ThemeCSS1.css, ThemeCSS2.css и ThemeCSS3.cssДо сих пор мы спокойно удаляли файл web.config приложения с уверенностью, что он будет вновь создан оболочкой. Тем более, что там содержалась только заготовка кода. Теперь пришла пора редактировать этот файл и удалять его уже будет жалко.
Ранее мы говорили, что при подключении к странице темы (в
наших примерах - MyTheme ) через свойство объекта DOCUMENT оболочка
автоматически вставляет соответствующий атрибут в директиву @Page этой страницы, тем самым подключая к
странице индивидуальную тему.
Например
<% @Page Language="C#" Theme="MyTheme" %>
Обычно проектировщики ратуют за одинаковое стилевое оформление
страниц и используют в каждой из них одну и ту же тему. В этом
случае удобнее будет не подключать каждую страницу к одной
и той же теме, а указать общую тему в
Откройте
страницы наших примеров, использующих темы, а именно: Page5.aspx, Page8.aspx, Page10.aspx,
и скопируйте их в файлы с именами TestTheme.aspx, TestCalendar.aspx, ThemeCSS.aspx соответственно
Удалите
в них из директивы @Page атрибут Theme ="MyTheme"
Вызывая
для каждой страницы контекстное меню и выполняя команду View in Browser,
исполните их по очереди, чтобы убедиться, что отключенная
тема в них не действует. Пока получилась грустная, унылая
картина
Откройте
на редактирование файл web.config и добавьте
в секцию <system.web> дескриптор
с указанием общей темы<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true"/>
<authentication mode="Windows"/>
<pages theme="MyTheme" />
</system.web>
</configuration>
Вновь
выполняя для каждой страницы команду View in Browser,
исполните файлы по очереди, чтобы убедиться, что тема
опять заработала так, как будто-бы она была индивидуально
подключена к каждой страницеЕсли нужно сделать так, чтобы общая тема действовала по умолчанию на множестве страниц, но не перезаписывала на них индивидуальные стилевые настройки элементов управления, то конфигурационный файл должен быть таким
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true"/>
<authentication mode="Windows"/>
<pages styleSheetTheme="MyTheme" />
</system.web>
</configuration>
Если на какой-нибудь странице нужно сделать так, чтобы общая тема не действовала на нее по умолчанию, то есть два варианта:
@Page атрибут Theme =" Другая_тема "@Page страницы нужно
вставить атрибут EnableTheming="false"CSS дескриптором <link> или
в CSS,
то отключение темы по умолчанию атрибутом EnableTheming="false" отключает
только skin -файлы, CSS все
равно останется подключенной.Во всех наших примерах мы создавали активные страницы в корневом виртуальном каталоге сайта. Но для сайта с тысячами страниц это неприемлемый способ. Страницы могут группироваться по любому признаку, например тематическому, и размещаться в отдельных папках развитой древовидной системы виртуальных каталогов. Корнем этого дерева должен быть виртуальный каталог сайта, его еще называют корнем Web-дерева.
В развитом Web-дереве применение общей темы по умолчанию является удобным способом стилизации страниц. В каждом каталоге можно разместить отдельный файл web.config со своей общей темой и все страницы этого каталога будут использовать эту тему по умолчанию.
До сих пор мы рассматривали случай, когда разработчик сам
жестко привязывает тему к странице или группе страниц. Но иногда
может возникнуть необходимость поручить выбор
темы для конкретной страницы пользователю с немедленным изменением
ее стилевого оформления. При этом неважно, была ли включена
на странице индивидуальная тема или по умолчанию применялась
тема
Все,
что нужно сделать, это предусмотреть на странице интерфейс
выбора темы, а в коде страницы динамически присвоить свойству Page. или Page.StyleSheetTheme выбранное пользователем
значение. При этом важно понимать, что тема настраивается
перед инициализацией страницы, поэтому соответствующий код
нужно поместить в обработчик Page_PreInit(). Если это сделать
позже, в обработчиках других событий, то попытка присвоить
новое значение свойству Page. или Page.StyleSheetTheme вызовет ошибку компиляции.
С другой стороны, прочитать выбор пользователя можно только после создания страницы, когда присваивать свойству темы новое значение уже поздно. Поэтому динамическое задание темы нужно выполнять в два этапа:
Page_PreInit() назначить новую темуПри перезапуске страницы она должна быть переадресована на
саму себя. Такую операцию можно выполнить либо
методом Response., либо
методом Server..
Первый метод реализует полный
цикл с
отправкой на броузер и автоматическим возвращением на сервер.
Он тратит лишнее
время на пересылку.
Второй метод перезапускает страницу сразу на сервере без цикла
через клиента. Но есть одна существенная особенность: оба метода сбрасывают состояние
вида всех элементов управления и запускают страницу как в при
первом запросе.
Поскольку выбирать не из чего, то мы применим
второй метод Server..
Рассмотрим все это на примере. Прежде всего, нужно создать несколько тем, чтобы было из чего пользователю выбирать.
В панели Sulution Explorer вызовите контекстное меню для папки MyTheme и выполните команду Copy
В панели Sulution Explorer вызовите контекстное меню
для папки App_Themes, где должны храниться
все темы приложения, и выполните на ней команду Paste два
раза, чтобы создать еще две темы
Присвойте
копиям имена, например, MyTheme1 и MyTheme2Обратите внимание, что новые темы имеют старое содержание, которое было-бы желательно подправить, чтобы наглядно видеть влияние выбранной темы на оформление страницы. Мы это сделаем попозже.
Учитывая, что протокол HTTP не поддерживает
сохранение состояний и что страница существует только на время
обработки обратной отсылки, выбранную пользователем тему нужно
где-то сохранять. Это могут быть -наборы
( куки -файлы) на компьютере клиента,
которые мы туда запишем без его ведома, если он забыл выключить
их поддержку. Это могут быть Session.
Через
панель Solution Explorer скопируйте в корневой
виртуальный каталог нашего сайта файл TestTheme.aspx и
назовите его TestSwitchThemes.aspx
Определите
новую страницу TestSwitchThemes.aspx стартовой
Откройте
файл TestSwitchThemes.aspx на редактирование
и добавьте в верхнюю часть страницы из
вкладки Standard элемент
списока DropDownList для выбора темы
Переименуйте ID списка в lstSwitchThemes
Через
панель Properties в режиме Events создайте
для списка заготовку обработчика события SelectedIndexChanged,
которое поступит на сервер с обратной отсылкой, если пользователь
изменит выбор в списке
Добавьте
на страницу перед списком серверный элемент Label с
именем lblFirstLoadИнтерфейсная часть страницы TestSwitchThemes.aspx примет следующий вид

Код интерфейсной части страницы TestSwitchThemes.aspx следующий
<%@ Page AutoEventWireup="true" CodeFile="TestSwitchThemes.aspx.cs"
Inherits="TestSwitchThemes" 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>
<asp:Label ID="lblFirstLoad" runat="server" Text="Label"></asp:Label>
<br />
<asp:DropDownList ID="lstSwitchThemes" runat="server"
OnSelectedIndexChanged="lstSwitchThemes_SelectedIndexChanged">
</asp:DropDownList>
<br />
<asp:BulletedList ID="BulletedList1" runat="server">
<asp:ListItem>Туризм</asp:ListItem>
<asp:ListItem>Спорт</asp:ListItem>
<asp:ListItem>Музыка</asp:ListItem>
<asp:ListItem Value="Танцы"></asp:ListItem>
</asp:BulletedList>
<asp:Label ID="Label1" runat="server" Text="Текстовая метка"></asp:Label>
<asp:CheckBox ID="CheckBox1" runat="server" Text="Флажок" /><br />
<br />
<asp:Button ID="Button1" runat="server" Text="Отправить" /></div>
</form>
</body>
</html>
Откройте
на редактирование файл кода TestSwitchThemes.aspx.cs и заполните
его такusing System;
public partial class TestSwitchThemes : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
lblFirstLoad.Text = "Первая загрузка страницы";
// Заполняем список именами каталогов тем
System.IO.DirectoryInfo themeDir =
new System.IO.DirectoryInfo(Server.MapPath("App_Themes"));
lstSwitchThemes.DataTextField = "Name";
lstSwitchThemes.DataSource = themeDir.GetDirectories();
lstSwitchThemes.DataBind();
}
else
lblFirstLoad.Text = "Повторная загрузка страницы";
}
protected void Page_PreInit(object sender, EventArgs e)
{
if (Session["Theme"] != null)
{
// Был ранее сохраненный выбор, включить его
Page.Theme = (string)Session["Theme"];
// Восстанавливаем новое состояние списка
lstSwitchThemes.SelectedIndex = (int)Session["index"];
// Восстанавливаем текущее состояние "Флажка"
CheckBox1.Checked = (bool)Session["Флажок"];
}
}
protected void lstSwitchThemes_SelectedIndexChanged(object sender, EventArgs e)
{
// Запоминаем новый выбор пользователя
Session["Theme"] = lstSwitchThemes.SelectedValue;
// Запоминаем новое состояние списка
Session["index"] = lstSwitchThemes.SelectedIndex;
// Сохраняем текущее состояние "Флажка"
Session["Флажок"] = CheckBox1.Checked;
// Первый вариант:
// Обновляем страницу с полным циклом,
// чтобы новая тема вступила в действие
//Response.Redirect(Request.Url.ToString());
// Второй вариант:
// Обновляем страницу без полного цикла,
// чтобы новая тема вступила в действие
Server.Transfer(Request.FilePath);
}
}
Сделаем некоторые пояснения по кодовой части страницы:
System, потому что:DirectoryInfo прописан
с Session, Server, Response, Request являются общедоступными свойствами класса System.Web.UI.Page,
который наследуется нашим классом TestSwitchThemes и явно
приобретает все эти свойстваSystem только потому, что в коде имеются
ключевые слова string, int, bool,
используемые при явном string, System. int,
System. bool.NET
Framework,
а не только специализированные Web-средстваТеперь осталось внести какое-либо видимое различие в оформления тем, чтобы мы могли убедиться, что программно была подключена действительно другая тема. Для экономии своих сил внесем минимальные изменения, например, сделаем разными цвета фона страницы.
Вызовите
на редактирование файл App_Themes/MyTheme1/ThemeCSS.css и
поменяйте в селекторе body определение
стиля фона background , чтобы фон страницы
стал зеленымbody
{
background:green;
font-family:Arial, Helvetica, sans-serif;
}
Вызовите
на редактирование файл App_Themes/MyTheme2/ThemeCSS.css и
поменяйте в селекторе body определение стиля
фона background , чтобы фон страницы стал краснымbody
{
background:red;
font-family:Arial, Helvetica, sans-serif;
}
Исполните
страницу и убедитесь в том, что пользователь может сам выбирать
варианты стилевого оформления страниц подключением соответствующих
темПодобным образом программно можно менять и другие стилевые
свойства страницы и ее элементов, например, именованные оформления элементов управления, определенные атрибутом SkinID. Не обязательно давать пользователю
возможность настройки стилевого оформления напрямую. Можно
сделать оформление страниц и элементов косвенно зависимым от
выбора пользователя.
Все, что было сказано для декларативного
способа подключения тем и приоритетов их применения, остается
справедливым и для
Очень часто требуется зафиксировать структуру страницы так, чтобы одни и те же элементы управления пользовательского интерфейса размещались в одном и том же месте как на одной странице, так и на множестве страниц сайта. Это позволяют сделать специальные страницы - шаблоны, которые существуют независимо, но подключаются к страницам по мере необходимости. Любая исполнимая страница может подключать только один из заранее заготовленных шаблонов.
Шаблон размечает
Перекомпоновка подключенного шаблона или его содержимого, а также подключение к исполнимой странице нового шаблона декларативно или программно приводит к немедленному изменению ее структуры и содержимого шаблонной части.
Исполнимая
страница получает от используемого шаблона его компоновку, содержимое и заполнитель. Заполнитель шаблона проецируется
на исполнимую страницу полностью. Если на исполнимой странице
есть хотя-бы одна группа, прикрепленная к соответствующей именованной
области шаблона, то

Замещающее содержимое на контекстной странице может располагаться
только в контейнерах, ссылающихся на зарезервированные мастер-страницей
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server"> </asp:Content>
Добавьте
к проекту командой Website/Add New Item шаблон с именем FirstMasterPage.master с
разделяемым кодом
Вот какой дескрипторный код создал мастер
<%@ Master Language="C#" AutoEventWireup="true"
CodeFile="FirstMasterPage.master.cs"
Inherits="FirstMasterPage" %>
<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>
Этот код почти такой-же, как и у заготовки обычной исполнимой страницы .aspx. Шаблоны представляют собой обычные страницы, за исключением нескольких отличий:
@Page используется директива @Master System.Web.UI.MasterPage ,
вместо базового класса System.Web.UI.Page для
обычной исполнимой страницыContentPlaceHolder используется
для резервирования именованных контекстных
областей только
в шаблонах. Если раскрыть вкладку Standard контекстно-зависимой
панели Toolbox при
редактировании обычной страницы, то мы этого элемента просто
не увидим, поскольку оболочка его скрывает до случая редактирования
шаблонаContentPlaceHolder ( держатель
места для содержимого ) шаблонной страницы можно размещать
в ячейках таблицы. При выполнении эти ячейки заполнятся присоединенным
содержимым, а остальные ячейки можно занять заполнителем,
который будет виден и доступен на любой странице, использующей
этот шаблон
Удалите
из кода ContentPlaceHolder и
через контекстное меню редактора выполните команду Add
Content Page (добавить
контекстную
страницу)
Оболочка сгенерирует такую заготовку файла Default.aspx
<%@ Page Language="C#" MasterPageFile="~/FirstMasterPage.master"
AutoEventWireup="true" CodeFile="Default.aspx.cs"
Inherits="_Default" Title="Untitled Page" %>
<%-- Add content controls here --%>
Получился пустой файл содержимого, где имеется только директива @Page
со стандартными атрибутами страницы и атрибутом подключения
шаблона.
<%--...--%> в
дескрипторный код файлов ASP.NETОболочка
прописала значение атрибута подключения MasterPageFile с
путем относительно корня Web-дерева сайта (там
наш шаблон и находится). Если уже подключенный к каким-то
страницам шаблон переместить из корня в другую папку Web-дерева,
то оболочка автоматически не меняет путь атрибута MasterPageFile во
всех ссылающихся на шаблон страницах, это придется делать
вручную. Поэтому нужно заранее
спланировать, будем ли мы использовать
Создайте
в панели Solution Explorer через контекстное
меню для корня Web-дерева проекта командой New Folder каталог MasterPages
Переместите
мышью в папку MasterPages шаблон FirstMasterPage.masterОткорректируем дескрипторный код контекстной страницы, для этого:
В панели Solution Explorer дайте файлу Default.aspx новое имя FirstMasterPage.aspx
Откорректируйте
дескрипторный код страницы FirstMasterPage.aspx,
указав новое местоположение шаблона, переименовав класс
поддержки страницы и назначив заголовок окна броузера<%@ Page Language="C#"
MasterPageFile="~/MasterPages/FirstMasterPage.master"
AutoEventWireup="true" CodeFile="FirstMasterPage.aspx.cs"
Inherits="FirstMasterPage" Title="Тестовая страница содержимого" %>
<%-- Add content controls here --%>
Откройте
файл FirstMasterPage.aspx.cs командой View
Code контекстного меню страницы и измените имя _Default класса страницы на FirstMasterPage
Назначьте
страницу FirstMasterPage.aspx стартовой
и исполните ее, чтобы убедиться в отсутствии ошибокПоявилась пустая страница с фоном, определенным темой по умолчанию MyTheme, включенной нами ранее в конфигурационный файл web.config
<configuration>
<system.web>
<pages theme="MyTheme" />
</system.web>
</configuration>
Никакого содержимого страница пока не имеет.
Добавьте
в файл FirstMasterPage.aspx произвольный
текст, например<%@ Page Language="C#"
MasterPageFile="~/MasterPages/FirstMasterPage.master"
AutoEventWireup="true" CodeFile="FirstMasterPage.aspx.cs"
Inherits="FirstMasterPage" Title="Тестовая страница содержимого" %>
<%-- Add content controls here --%>
<h1>Привет студентам из "страницы содержимого1"!</h1>
Если сейчас исполнить такую страницу, то мы получим ошибку времени выполнения, потому что содержимое страницы должно находиться в специальных именованных контейнерах
<asp:Content></asp:Content>
Поместите
строку текста в контейнер <asp:Content> и
исполните страницу<%@ Page Language="C#"
MasterPageFile="~/MasterPages/FirstMasterPage.master"
AutoEventWireup="true" CodeFile="FirstMasterPage.aspx.cs"
Inherits="FirstMasterPage" Title="Тестовая страница содержимого" %>
<%-- Add content controls here --%>
<asp:Content>
<h1>Привет студентам из "страницы содержимого1"!</h1>
</asp:Content>
Вновь произойдет ошибка выполнения, потому что каждый
контейнер <asp:Content></asp:Content> обязательно
должен ссылаться на свою
Откройте
на редактирование файл ~/MasterPages/FirstMasterPage.master в
режиме Design и поместите на шаблон из вкладки Standard элемент управления ContentPlaceHolder,
экземпляр которого мы ранее удалили
Перейдите
в режим Source на странице FirstMasterPage.master и
поместите внутрь созданного контейнера ContentPlaceHolder1 текстовую
строку, чтобы дескрипторный код стал таким<%@ Master Language="C#" AutoEventWireup="true"
CodeFile="FirstMasterPage.master.cs"
Inherits="FirstMasterPage" %>
<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">
<h1>Привет студентам из "именованной области1" мастер-страницы!</h1>
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Перейдите
в режим Design и убедитесь, что 
Теперь нужно настроить контекстную страницу, использующую шаблон.
Откройте
на редактирование в режиме Source контекстную
страницу FirstMasterPage.aspx,
к которой подключен шаблон, и определите в контейнере <asp:Content> идентификатор-ссылку ContentPlaceHolderID резервируемой
области шаблона, на которую будет ссылаться контекстный дескрипторПользуйтесь услугами подсказчика кода ,
который вызывается каждый раз при добавлении пробела внутри
дескриптора. Идентификатор ID самого контейнера <asp:Content> в
контекстной
странице определять необязательно, если только
мы не планируем управлять им программно. Измененный
код будет таким
<%@ Page Language="C#"
MasterPageFile="~/MasterPages/FirstMasterPage.master"
AutoEventWireup="true" CodeFile="FirstMasterPage.aspx.cs"
Inherits="FirstMasterPage" Title="Тестовая страница содержимого" %>
<%-- Add content controls here --%>
<asp:Content ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<h1>Привет студентам из "страницы содержимого1"!</h1>
</asp:Content>
Исполните
страницу FirstMasterPage.aspx, должен получиться
такой результат с учетом действия темы MyTheme,
подключенной в 
Поместите
на шаблон еще один резервирующий контейнер ContentPlaceHolder и
наполните его таким кодом<%@ Master Language="C#" AutoEventWireup="true"
CodeFile="FirstMasterPage.master.cs"
Inherits="FirstMasterPage" %>
<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">
<h1>Привет студентам из "именованной области1" мастер-страницы!</h1>
</asp:ContentPlaceHolder>
<br />
<asp:ContentPlaceHolder ID="ContentPlaceHolder2" runat="server">
<h1>Привет студентам из "именованной области2" мастер-страницы!</h1>
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Перейдите
на контекстную
страницу FirstMasterPage.aspx в
режиме Design, которая станет такой
Мы видим, что
Мы можем рассматривать итоговую страницу пользователя как
двухслойную. На нижнем слое находится
Иными словами,
Обратите внимание на заголовки именованных областей и их фон.
Там, где подставлено содержимое прикрепленного контейнера,
фон светлее и в скобках надпись ( Custom ) -
заказной. Там, где проявилось содержимое
Добавим непустой контейнер содержимого к нижней резервируемой
области
На
странице FirstMasterPage.aspx в режиме Design вызовите
контекстное меню для нижней зарезервированной области и выполните
команду Create Custom ContentОболочка добавит пустой контейнер содержимого и автоматически свяжет его в дескрипторном коде с именованной резервируемой областью.
Добавьте
в контейнер с содержимым какой-нибудь текст и несколько компонентов
из панели Toolbox и выполните страницуЭто очень удобная технология. Если планируется создание
нескольких страниц на базе
После того, как на вновь созданной странице с содержимым проявятся
На
нижней области контекстной
страницы FirstMasterPage.aspx вызовите
контекстное меню и выполните команду Default to Master's
Content, чтобы удалить содержимоеЕсли
Приведем более содержательный пример разработки страниц с
использованием шаблонов. Учитывая, что HTML поддерживает только
потоковую
В панели Solution Explore r вызовите контекстное меню
для папки MasterPages, которую мы
создали ранее,
и выполните команду Add New Item
В окне
мастера создания заготовок выберите шаблон Master
Page и создайте эталонную страницу с именем Title.master без
файла отделенного кода
Оболочка добавит заготовку эталонной страницы в каталог MasterPages, где ей и место.
Переведите
в редакторе эталонную страницу Title.master в
режим Design и удалите пока автоматически
созданный экземпляр элемента ContentPlaceHolder (просто
для тренировки)
В
режиме Design из вкладки Standard панели Toolbox поместите
в самом начале Image как
контейнер для размещения ID =" ImageBanner "Элемент Image из вкладки HTML здесь
не подойдет. Он не будет проявляться на контекстной
странице,
потому что не обрабатывается сервером по механизму runat="server" )
Вызовите
контекстное меню для папки MasterPages и
выполните команду Add Existing Item.
Найдите через открывшееся диалоговое окно файл Banner.png,
который находится в прилагаемом к данной работе каталоге Source,
и скопируйте его в папку MasterPages текущего
сайта
Выделите
экземпляр ImageBanner и присоедините
к нему через свойство ImageUrl рисунок Banner .png из
папки MasterPages Web-дерева сайта
Наш
Разместите
после <h1 style="color: Green">
Мы приветствуем Вас на нашем сайте!!!
</h1>
Элемент шаблона ContentPlaceHolder по умолчанию
растягивается по всей ширине страницы. Чтобы позиционировать
его на

В трех ячейках таблицы будет размещаться потенциально заменяемое
содержимое ContentPlaceHolder. В разных ячейках
таблицы мы сделали разный фон только для учебных целей, чтобы
сделать ячейки видимыми и показать, что фон ячеек таблицы с
Мы должны четко
представлять, что элементы управления ContentPlaceHolder и Content являются прозрачными контейнерами
для своего содержимого, если только мы искусстенно не создадим
в них фон другими элементами, например, элементом Panel, Image, Table. Поэтому, если мы на странице содержимого
не создадим свой фон в замещающих элементах Content,
то будет проявляться в итоговой странице фон элемента-контейнера
Поместите
на Table
Используя
боковые маркеры таблицы и команды меню Layout оболочки, постройте
таблицу из трех строк и двух столбцов, чтобы она соответстворвала
приведенному выше рисункуВ конечном виде таблица вместе с вутренними стилями должна описываться следующими HTML -кодом
<table>
<tr>
<td colspan="2">
</td>
</tr>
<tr>
<td style="width: 25%; background-color: #9DFF7E" valign="top">
</td>
<td style="background-color: #FFB8FF">
</td>
</tr>
<tr style="background-color: #FFFF92">
<td colspan="2">
</td>
</tr>
</table>
Внешний вид таблицы будет таким

Теперь все готово для размещения элементов управления
в ячейках
Поместите
из вкладки Standard панели Toolbox в
верхнюю строку таблицы компонент Panel,
к которому мы должны присоединить рисунок, задающий
фон ячейки
Задайте
для созданного экземпляра элемента управления Panel значения свойств: Width=100% ; Height=100%, чтобы элемент полностью занял верхнюю ячейку
таблицы
Через
проводник Windows найдите в
прилагаемом к данной работе каталоге Source файл BackTitleSrc.jpg и в любом графическом
редакторе вырежьте из него область с хорошо стыкуемыми
при повторении рисунка границами, или возьмите
мною вырезанный готовый рисунок BackTitle.jpgРисунок не должен быть слишком большим, чтобы "не застревал в проводах и не тормозил " по пути к пользователю.
В
панели Solution Explorer в
контекстном меню для папки MasterPages выполните
команду Add Existing Item,
найдите рисунок BackTitle.jpg и
скопируйте его в эту папку
Выделите
на странице экземпляр Panel1 в
верхней строке таблицы и через панель инструментов Properties присоедините
в свойстве BackImageUrl
рисунок BackTitle.jpg, который многократным повторением займет
всю Теперь можно разместить в ячейках таблицы прозрачные
контейнеры-шаблоны элемента управления ContentPlaceHolder.
Поместите
из вкладки Standard панели Toolbox в
верхнюю строку таблицы в объект Panel1 элемент-контейнер ContentPlaceHolder, который
будет представлять на странице именованную
область ContentPlaceHolder1 для
размещения
То
же самое сделайте для правой-средней и нижней
ячеек таблицы
В
контейнер ContentPlaceHolder1 вставьте
и отредактируйте такую строку<div style="font-weight: bold; font-size: xx-large; color: red; text-align: center">
Сведения об автошколе в целом
</div>
Вставьте
в правый-средний контейнер ContentPlaceHolder2 любой
текст, например, такой или его частьВот уже более 15 лет мы занимаемся подготовкой водителей
категории "B" в г.Красноярске и всегда занимали первые места
в сводках МРЭО ГИБДД по качеству обучения. Автошкола всегда нацелена
на успех наших клиентов в сдаче экзаменов ГАИ с первого раза
и своевременном получении водительского удостоверения.
Мы обеспечиваем максимальные удобства своим клиентам. Для
этого существуют вечерняя и воскресная формы обучения.
Наши курсанты имеют возможность бесплатно и неограниченно пользоваться
компьютерным классом. Учебные автомобили прибывают по заявке
клиента к назначенному им месту. Развивается сеть филиалов автошколы
в г.Красноярске.
Наша компьютерная экзаменационная программа успешно используется
в ГИБДД г.Красноярска, Железногорска, Назарово, Емельяново, Шарыпово
для государственной аттестации кандидатов в водители. Мы неоднократно
выпускали цветные учебно-методические пособия по Правилам дорожного
движения, которыми постоянно пользуются большинство автошкол
города и края.
Лекционные занятия в автошколе ведут квалифицированные преподаватели
с учеными степенями и званиями с применением современных компьютерных
технологий. Комплексный подход к обучению и разнообразие форм
позволяют максимально сократить усилия наших клиентов и сроки
усвоения ими учебного материала. Парк учебных автомобилей насчитывает
более 30 штук, включая иномарки.
В
нижний контейнер ContentPlaceHolder3,
резервирующий место под <strong> Автошкола Диалог-Сервис в целом работает без перерыва на обед и выходных с 8 часов утра до 9 часов вечера!!! </strong>
Поместите
в левую ячейку таблицы надпись, а из вкладки Standard панели Toolbox три гиперссылки
элемента управления HyperLink Дескрипторный код содержимого левой ячейки таблицы,
которое размещается внутри тегов <td></td>,
будет примерно таким
<strong style="color: Blue">Наши филиалы:</strong><br /> <br /> <asp:hyperlink id="HyperLink1" runat="server">Ленинский район</asp:hyperlink><br /> <br /> <asp:hyperlink id="HyperLink2" runat="server">Центральный район</asp:hyperlink><br /> <br /> <asp:hyperlink id="HyperLink3" runat="server">Свердловский район</asp:hyperlink><br /> <br /> <asp:hyperlink id="HyperLink4" runat="server">Октябрьский район</asp:hyperlink>
Сейчас мы пока не определяем в гиперссылках элементы
адресации до тех пор, пока не создадим несколько
контекстных
страниц, использующих эту
Итак, таблицу мы заполнили. Попробуем разместить
еще что-нибудь ниже таблицы, например, товарный
знак и страшилку от воров
Отступите
ниже таблицы одну-две строчки и добавьте из вкладки HTML панели Toolbox элемент
управления Image.
Щелкните на нем правой кнопкой мыши и выполните
команду Run As Server Control,
чтобы содержимое элемента проявилось на будущей
контекстной
странице как заполнитель
В
панели Solution Explorer вызовите
контекстное меню для папки MasterPages и
скопируйте в проект командой Add Existing
Item из
прилагаемого каталога Source рисунок LIGHT.ICO нашего
Через
панель Properties и свойство Src ( Source - источник) присоедините ссылку на файл LIGHT .ICO к
нашему компоненту отображения Image
Правее
Окончательный дескрипторный код этого раздела будет таким
<p style="text-align: right; color: Blue; font-family: 'Courier New'; font: bold italic">
<img id="IMG1" runat="server" src="LIGHT.ICO" />
nbsp;Copyright copy 2009
</p>
Для
наглядности, поместите еще один контейнер в самом
низу <asp:ContentPlaceHolder ID="ContentPlaceHolder4" runat="server">
<strong><em>Вы уж, пожалуйста, наведывайтесь к нам почаще!</em></strong>
</asp:ContentPlaceHolder>
И последний штрих к оформлению
Найдите
вверху дескрипторного кода самый внешний дескриптор <div> и определите в нем
внутренний стиль CSS такой<body>
<form id="form1" runat="server">
<div style="text-align: center">
..................................
</div>
</form>
</body>
Наступил момент истины! Пора тиражировать контекстные
страницы на базе созданной
В продолжение упражнения создадим 5 контекстных страниц с простыми именами:
Есть несколько способов создания с помощью
оболочки контекстных страниц
на базе готовой
В
панели Solution Explorer выделите корень Web-дерева и выполните команду меню Website/Add
New Item (или команду Add New Item контекстного меню)
В
появившемся диалоговом окне задайте имя страницы Satellite.aspx и отметьте показанные настройки,
включая Select
master page
Оболочка
предложит еще одно окно, в котором выберите

Созданная страница Satellite.aspx с
отделенным кодом будет добавлена в корень Web-дерева
и будет содержать контейнеры с подключенным пустым
содержимым для всех шаблонов выбранной
<%@ Page Language="C#" MasterPageFile="~/MasterPages/Title.master"
Title="Untitled Page" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder2" Runat="Server">
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder3" Runat="Server">
</asp:Content>
<asp:Content ID="Content4" ContentPlaceHolderID="ContentPlaceHolder4" Runat="Server">
</asp:Content>
В
панели Solution Explorer выделите
нужную Будет создана контекстная
страница с дежурным
именем, размещенная в том же каталоге, что и выделенная
MasterPageFile будет
прописан относительно корня Web-дерева как абсолютный
адрес в пределах сайта
MasterPageFile="~/
Это значит, что можно переместить
контекстную
страницу в любую
папку в пределах Web-дерева, и везде адрес
Поэтому необходимо
соблюдать простое правило, при котором не
придется долго искать ошибки:
перемещать
Переименуйте
созданную контекстную страницу Default.aspx на Satellite1.aspx и
переместите ее в
Откройте
Появится контекстное меню с уже известной нам командой Add Content Page, выполнение которой создаст файл Default.aspx.
Переименуйте
созданную контекстную страницу Default.aspx на Satellite2.aspx и
переместите ее в
Получите
в Теперь необходимо скорректировать заготовки контекстных
страниц
Выполните
команду Window/Close All Documents,
чтобы закрыть все редактируемые
на текущий момент файлы
В
панели Solution Explorer щелкните
правой кнопкой мыши на файле ~/MasterPages/Title.master и
выполните команду View Designer, чтобы открыть
Поочередно
выделяя элементы гиперссылок, установите их свойство NavigateUrl на соответствующие
контекстные
страницы Satellite1.aspx, Satellite2.aspx, Satellite3.aspx, Satellite4.aspx.
Сохраните и закройте Отредактируем страницы содержимого, начнем с Satellite.aspx.
В
панели Solution Explorer назначьте
страницу Satellite.aspx стартовой
и откройте ее на редактирование в режиме Design Что мы видим на данном этапе времени проектирования:
Удалите
в режиме Design командой контекстного
меню Default
to Master 's Content все контейнеры контекста <asp:Content></asp:Content>
из
страницы Satellite.aspxЭта страница у нас будет стартовой без своего
содержимого и будет отображать только содержимое
Убедитесь,
что после удаления закрепленных блоков контекстной
страницы проявился нижний слой - содержимое шаблонов
Исполните
страницу Satellite.aspx, получится
ожидаемый результат
Пощелкайте
по ссылкам и обратите внимание, как меняется
адрес в броузере (ссылки работают). На адресуемых
страницах мы пока не убрали и не изменили контейнеры
содержимого, поэтому там на месте контейнеров
шаблона ничего не будет (пустое содержимое контейнеров
место при исполнении не занимает).Теперь нужно наполнить контекстные страницы, которые мы подгружаем по ссылкам, индивидуальным содержимым.
Приведем окончательный вариант дескрипторного кода для всех страниц данного примера:
Обратите внимание, что все контейнеры ContentPlaceHolder должны находиться внутри
дескриптора <form></form>.
<%@ Master Language="C#" %>
<script runat="server">
</script>
<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">
nbsp;<asp:Image ID="ImageBanner" runat="server" ImageUrl="~/MasterPages/Banner.png" /><br />
nbsp;<h1 style="color: green">
Мы приветствуем Вас на нашем сайте!!!
</h1>
<table>
<tr>
<td colspan="2">
<asp:Panel ID="Panel1" runat="server" BackImageUrl="~/MasterPages/BackTitle.jpg"
Height="100%">
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
nbsp;<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">
<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><br />
<br />
<asp:HyperLink ID="HyperLink4" runat="server" NavigateUrl="~/Satellite4.aspx">Октябрьский район
</asp:HyperLink>
</td>
<td style="background-color: #FFB8FF">
<asp:ContentPlaceHolder ID="ContentPlaceHolder2" runat="server">
<p>Вот уже более 15 лет мы занимаемся подготовкой водителей
категории "B" в г.Красноярске и всегда занимали первые места
в сводках МРЭО ГИБДД по качеству обучения. Автошкола всегда нацелена
на успех наших клиентов в сдаче экзаменов ГАИ с первого раза
и своевременном получении водительского удостоверения.</p>
<p>Мы обеспечиваем максимальные удобства своим клиентам. Для
этого существуют вечерняя и воскресная формы обучения.
Наши курсанты имеют возможность бесплатно и неограниченно пользоваться
компьютерным классом. Учебные автомобили прибывают по заявке
клиента к назначенному им месту. Развивается сеть филиалов автошколы
в г.Красноярске.</p>
<p> Наша компьютерная экзаменационная программа успешно используется
в ГИБДД г.Красноярска, Железногорска, Назарово, Емельяново, Шарыпово
для государственной аттестации кандидатов в водители. Мы неоднократно
выпускали цветные учебно-методические пособия по Правилам дорожного
движения, которыми постоянно пользуются большинство автошкол
города и края. </p>
<p> Лекционные занятия в автошколе ведут квалифицированные преподаватели
с учеными степенями и званиями с применением современных компьютерных
технологий. Комплексный подход к обучению и разнообразие форм
позволяют максимально сократить усилия наших клиентов и сроки
усвоения ими учебного материала. Парк учебных автомобилей насчитывает
более 30 штук, включая иномарки.</p>
</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 copy 2009
</p>
<asp:ContentPlaceHolder ID="ContentPlaceHolder4" runat="server">
<strong><em>Вы уж, пожалуйста, наведывайтесь к нам почаще!</em></strong>
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Все контейнеры <asp:Content> уничтожены,
поэтому страница используется только как запускающая
и не добавляет к
<%@ Page Language="C#" MasterPageFile="~/MasterPages/Title.master"
Title="Untitled Page" %>
Страница имеет все контейнеры переопределяющего
содержимого, поэтому от
<%@ 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>
Страница имеет все контейнеры переопределяющего
содержимого, поэтому от
<%@ 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>
Третий контейнер страницы содержимого отсутствует,
поэтому на его месте проявится содержимое третьего
шаблона
<%@ 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>
Второй контейнер страницы отсутствует,
поэтому на его месте проявится содержимое второго
шаблона
<%@ Page Language="C#" MasterPageFile="~/MasterPages/Title.master" Title="Untitled Page" %>
<asp:Content runat="Server" ContentPlaceHolderID="ContentPlaceHolder1">
<div style="font-weight: bold; font-size: xx-large; color: red; text-align: center">
Сведения о филиале в Октябрьском районе
</div>
</asp:Content>
<asp:Content runat="Server" ContentPlaceHolderID="ContentPlaceHolder3">
</asp:Content>
<asp:Content runat="Server" ContentPlaceHolderID="ContentPlaceHolder4">
</asp:Content>
Прежде, чем приступить к программному управлению
элементов
Такой порядок означает, что если мы программно
меняем одни и те же настройки в
В контекстной странице мы можем менять
только содержимое контейнеров <asp:Content>,
а содержимое заполнителей
Вначале рассмотрим вопросы программирования заголовка
<head> в HTML-выводе. <head>...</head> обычной
страницы, где можно задавать все составляющие его
дескрипторы и это появится на результирующей странице.
Но иногда на контекстной странице нужно определить
свои дескрипторы заголовка. Декларативно (на
этапе проектирования) в контекстной странице
можно переопределить только дескриптор <title>,
добавив в
директиву @Page атрибут Title="..." контекстной
страницы. В этом случае дескриптор <head>
Программно можно переопределять не только дескриптор <title>,
но и другие дескрипторы заголовка <head> <head> Page Page. объекта
текущей контекстной страницы, у которого, в свою
очередь, свойство и
определяет ссылку на объект Page
Ниже
приведены равноценные коды получения ссылки на
объект Page
Page masterPage = base.Master.Page;
Page masterPage = this.Master.Page;
Page masterPage = Master.Page;
Ключевые слова base или this не
являются обязательными. Они напоминают, что является
свойством объекта текущей страницы.
Создайте
копию страницы 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" %>
Исполните
страницу с новым заголовком окна броузера - результат
будет таким
Поскольку мы не создавали для страницы 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() срабатывает позднее.
Рассмотрим управление элементами заполнителя <h1>,
определенного в заполнителе так
<h1 style="color: Green">
Мы приветствуем Вас на нашем сайте!!!
</h1>
Его отображение в броузере будет следующим

Дополните
дескриптор <h1> Title.master необходимыми
для программного управления атрибутами<h1 style="color: Green" runat="server" id="Header1">
Мы приветствуем Вас на нашем сайте!!!
</h1>
Управлять будем из страницы SatelliteExt.aspx одним из двух способов:
<h1> в
отдельное свойство с именем MyHeader1 и
из контекстной страницы будем обращаться к
нему через это свойство<h1> по
его ID и будем
обращаться к нему напрямую
Двойным
щелчком на
свободном от элементов управления месте <%@ 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>
Дополните
контекстную страницу 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>
Исполните
контекстную страницу 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>
Метод FindControl() ищет указанный
элемент на
Исполните
страницу SatelliteExt.aspx и
убедитесь, что дескриптор <h1>,
относящийся к заполнителю 
Второй способ более предпочтительный, поскольку
мы не вмешиваемся в код спроектированной
Иногда может возникнуть необходимость дать возможность
пользователю подключать необходимые Page. в
директиве @Page. Теперь нам нужно программно
менять атрибут Page.MasterPageFile в
коде контекстной страницы.
Здесь нужно иметь ввиду следующее:
ContentPlaceHolderIDPage.PreInit контекстной
страницы.
Если это сделать в обработчиках более поздних
событий, то будет сгенерировано исключениеУчитывая, что наши страницы Satellite.aspx, Satellite1.aspx, Satellite2.aspx, Satellite3.aspx согласованы
с Title.master, сделаем их копии
и настроим под динамическую смену
В
панели Solution Explorer создайте копию файла Title.master с
именем Title1.master
Откройте
<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 стартовой
Откройте
<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] |
~/ |
|
Items[1] |
~/ |
Установите
для списка 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>
Откройте
поочередно файлы 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>
Исполните
начальную страницу SatelliteDynamic.aspx и
убедитесь, что мы дали пользователю полнофункциональный
механизм выбора шаблонов форматированияПринципиально возможно подключение одной
Но мы, все-таки, рассмотрим эту
возможность на примере Level1 к верхнему Level0.
Создайте в корне Web-дерева 
Код
страницы сделайте таким<%@ 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>
Теперь
также в корне 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>
Обратите внимание, что при попытке переключить
созданную

Это значит, что автоматизированный графический
режим Design
работает только для
Выполните
для страницы 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>
Назначьте
контекстную страницу TestMasterPageLevel.aspx стартовой
и исполните ееРезультат будет таким

Итак, все работает, но нам это не надо - слишком запутано и посмотреть в Design нельзя!
Для страниц, которые не имеют подключения
<configuration>
<system.web>
<pages masterPageFile="XXX.master" />
</system.web>
</configuration>
Этот подход не считается надежным, поскольку
требует строгого согласования всех контекстных
страниц с шаблонами одной

Файлы к лабораторной работе Вы можете скачать здесь.
Единообразие в оформлении множества отдельных страниц сайта является важной его характеристикой. Visual Studio 2005 имеет три возможности для поддержки стилевого оформления (форматирования) сайта:
Каскадными таблицы называют потому, что каждая из них реализует
принцип: стиль внутреннего каскада перекрывает действие стилей
всех внешних каскадов. Это устоявшееся средство стилевого оформления,
которое входит в HTML4 и
поддерживается практически всеми броузерами.
<head> и
имеет описание стилей общее для тех дескрипторов страницы,
на которые она должна действовать. Это индивидуальная настройка
стилей для страницы и бластью их действия являются теги только
одного документаПо отношению к этим трем типам CSS также соблюдается свойство каскадности, т.е. стиль внутреннего каскада имеет более высокий приоритет и перекрывает действие внешнего стиля.
Кратко рассмотрим все перечисленные типы CSS и их поддержку оболочкой Visual Studio 2005.
Стиль отдельного дескриптора определяется атрибутом style.
Синтаксис применения внутреннего стиля на примере дескриптора <h1> будет
таким

Значением стилевого атрибута является строка, представляющая
пары ' стиль:значение ', отделенные друг от
друга разделителем 'точка с запятой' или пробелом. Определенный
в дескрипторе внутренний стиль будет действовать только на
свой дескриптор и перекрывать все определения внешних стилей.
Командой
главного меню оболочки File/New/Website создайте новый пустой проект
с именем PageStyles
Командой
главного меню оболочки Website/Add New Item добавьте
в корневой узел проекта 
Запустите
утилиту WAT (Web Site
В открывшемся
окне броузера на странице WAT перейдите
на вкладку Application, щелкните на ссылке Configure debugging and tracing и в появившейся
странице включите флажок Enable debuggingВыполненное действие установит в debug в значение true.
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<appSettings/>
<connectionStrings/>
<system.web>
<compilation debug="true" />
<authentication mode="Windows" />
</system.web>
</configuration>
Добавьте
к проекту 
Поместите
внутрь дескриптора <body>
заголовочный дескриптор с внутренними стилевыми настройками,
дескриптор горизонтальной линии и ссылку на следующую страницу<h1 style="color: red; text-align: center">
Этот заголовочный текст будет центрирован в
сгенерированном документе и иметь красный цвет!
</h1>
<hr />
<a href=Page2.htm>Вперед</a>
Запустите
текущую страницу и убедитесь, что внутренний стиль дескриптора
действует
Определение внутренних стилей отдельных дескрипторов используется
редко. Чаще применяются встроенные стили, которые действуют
в пределах всей страницы. Встроенные стили не разбросаны по
странице, а размещаются внутри дескрипторного блока <head>...</head> в
специальном стилевом контейнере <style>...</style>.
Синтаксис встроенных стилей следующий

Атрибут type="text/css" дескриптора
стиля указывает броузеру, что ниже перечислены стили, которые
нужно применить к тексту при его отображении. Внутри стилевого
блока описываются именованные группы пар 'стиль:значение' с
разделителем 'точка с запятой', которые называются селекторами.
Имена селекторов могут совпадать с именами дескрипторов, например,
в приведенном выше примере селекторы body и h1 совпадают
с именами дескрипторов HTML. В этом случае дополнительных
указаний внутри дескрипторов не требуется.
Если используется список селекторов с определенными идентификаторами, то описанный в списке стиль применяется к элементам страницы с указанными идентификаторами и дополнительных указаний внутри именованных дескрипторов не требуется.
В качестве универсальных меток стилей могут использоваться
селекторы классов " .имя_класса ". Тогда в тех дескрипторах документа,
где необходимо применить определенный в классе стиль, должен
присутствовать атрибут class=" имя_класса".
Классы для конкретного вида тегов " тег.имя_класса " используются
только в тегах заданного типа по той же самой схеме class=" имя_класса".
Имена классов " .имя_класса " выбираются
произвольно.
Элементы списка селекторов отделяются друг от друга запятыми или пробелами. Если в определение одного свойства подразумевается много значений, то они также разделяются запятыми или пробелами. Если одно значение правила состоит из нескольких частей, разделенных пробелами, то оно обязательно заключается в двойные или одинарные кавычки.
В панели Solution Explorer вызовите контекстное меню
для корневого узла проекта и командой New Folder добавьте
папку с именем Resources
В панели Solution Explorer вызовите контекстное меню
для узла Resources и командой Add Existing Item скопируйте
в папку Resources из прилагаемого к работе
каталога Source файлы BackgroundImage.bmp и Web.jpg
Добавьте
к проекту <html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Документ со встроенной CSS</title>
<meta content="text/html; charset=windows-1251" http-equiv="Content-Type">
<style type="text/css">
body
{
background:url(Resources/Web.jpg);
font-family:Arial, Helvetica, sans-serif;
}
h1
{
color:#FF0000;
text-align:center;
}
#TextBox1
{
font-family:"Courier New", Courier, mono;
font-size:24px;
font:bold italic;
background-color:#0000FF;
color:yellow;
width:400;
}
.btnResult
{
background-image:url(Resources/BackgroundImage.bmp);
color:white;
}
</style>
</head>
<body>
<h1>
Заполните анкету!
</h1>
<form id="form1" action="Page2.htm">
<p>
Введите ФИО:
<input id="TextBox1" name="TextBox1" type="text">
</p>
<p>
Введите ИНН:
<input id="TextBox2" name="TextBox2" type="text">
</p>
<center>
<input id="Button1" class="btnResult" name="Button1"
type="button" value="Отослать">
</center>
</form>
</body>
</html>
Запустите
страницу Page2.htm и проверьте результат
Внешними считаются стили, которые хранятся в отдельном файле
<style></style><head>...</head> дескриптора <link> или
директивы @impotПусть имеется два файла с внешними стилями и произвольными
именами, например, header.css и default.css.
Варианты их подключения в HTML-документ Page3.htm ( обязательно в
заголовочный блок <head>...</head> )
приведены в таблице:
| Вариант | В блоке <head> файла Page3.htm |
Замечания |
|---|---|---|
| Подключается одна CSS | <link rel="stylesheet" href="header.css"> |
|
| Подключается две CSS | <link rel="stylesheet" href="header.css"> <link rel="stylesheet" href="default.css"> |
|
| Подключается одна CSS | <style type="text/css"> @import url(header.css); </style> |
Не поддерживается |
| Подключается две CSS | <style type="text/css"> @import url(header.css); @import url(default.css); </style> |
Не поддерживается |
| Подключается две CSS ( в страницу импортируется цепочка CSS) | <style type="text/css"> @import url(header.css); </style> |
В самом начале файла header.css имеется голая строка
прямого подключения: |
| Подключается две CSS | <style type="text/css"> @import url(header.css); </style> <link rel="stylesheet" href="default.css"> |
Порядок следования не влияет |
| Подключается две CSS | <link rel="stylesheet" href="default.css"> <style type="text/css"> @import url(header.css); </style> |
Порядок следования не влияет |
| Подключается три CSS | <link href="default.css" rel="stylesheet">
<style type="text/css">
@import url(header.css);
body
{
background:white url(Web.jpg);
font-family:Arial, Helvetica, sans-serif;
}
h1
{
color:#FF0000;
text-align:center;
}
#TextBox1
{
font-family:"Courier New", Courier, mono;
font-size:24px;
font:bold italic;
background-color:#0000FF;
color:yellow;
width:400;
}
.btnResult
{
background-image:url(BackgroundImage.bmp);
color:white;
}
</style>
|
Подключается две внешних таблицы в дополнение к встроенной. Встроенные стили теоретически должны иметь выше приоритет, чем внешние. Но это зависит от конкретного броузера. Поэтому, чтобы избежать недоразумений, одновременно применять внешние и встроенные таблицы стилей не следует. Порядок следования не влияет |
| Подключается три CSS | <style type="text/css">
body
{
background:white url(Web.jpg);
font-family:Arial, Helvetica, sans-serif;
}
h1
{
color:#FF0000;
text-align:center;
}
#TextBox1
{
font-family:"Courier New", Courier, mono;
font-size:24px;
font:bold italic;
background-color:#0000FF;
color:yellow;
width:400;
}
.btnResult
{
background-image:url(BackgroundImage.bmp);
color:white;
}
@import url(header.css);
</style>
<link href="default.css" rel="stylesheet">
|
Подключается две внешних таблицы в дополнение к встроенной. Встроенные стили теоретически должны иметь выше приоритет, чем внешние. Но это зависит от конкретного броузера. Поэтому, чтобы избежать недоразумений, одновременно применять внешние и встроенные таблицы стилей не следует. Порядок следования не влияет |
Применим рассмотренный материал на практике.
В панели Solution Explorer найдите страницу Page2.htm и
сделайте из нее две копии с именами Page3.htm и ExternalCSS.css
Откройте файл Page3.htm и
замените в заголовке <head> встроенный
стиль на строку подключения внешней каскадной таблицы
стилей<link rel="stylesheet" href=" ExternalCSS.css">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Документ со встроенной CSS</title>
<meta content="text/html; charset=windows-1251" http-equiv="Content-Type">
<link href="ExternalCSS.css" rel="stylesheet">
</head>
<body>
<h1>
Заполните анкету!
</h1>
<form id="form1" action="Page3.htm">
<p>
Введите ФИО:
<input id="TextBox1" name="TextBox1" type="text">
</p>
<p>
Введите ИНН:
<input id="TextBox2" name="TextBox2" type="text">
</p>
<center>
<input id="Button1" class="btnResult" name="Button1"
type="button" value="Отослать">
</center>
</form>
</body>
</html>
Откройте файл ExternalCSS.css и
оставьте только чистый код селекторов и определений стилейbody
{
background:url(Resources/Web.jpg);
font-family:Arial, Helvetica, sans-serif;
}
h1
{
color:#FF0000;
text-align:center;
}
#TextBox1
{
font-family:"Courier New", Courier, mono;
font-size:24px;
font:bold italic;
background-color:#0000FF;
color:yellow;
width:400;
}
.btnResult
{
background-image:url(Resources/BackgroundImage.bmp);
color:white;
}
Откройте
страницу Page3.htm в броузере и убедитесь,
что получился тот же результат, что и при использовании
встроенных стилей в странице Page2.htm
Опробуйте
другие варианты подключения внешней CSS,
приведенные ранее в таблицеИтак, внешняя CSS, это обычный текстовый файл, которому традиционно назначают расширение .css для лучшей узнаваемости, хотя может использоваться любое другое расширение. Его можно создавать отдельно в любом текстовом редакторе, а затем использовать в Web-проекте. Но Visual Studio 2005 имеет свои встроенные средства создания CSS. Рассмотрим их.
Добавьте
в корневой узел сайта командой Website/Add New Item новый
файл типа Style Sheet с
именем StyleSheet.css (по
умолчанию)
Оболочка добавит в проект новый файл
Наша главная задача, как программистов, - понимать и правильно применять CSS, а на чем она подготовлена или кем (пусть у дизайнеров голова болит), не очень важно. Но если приспичит, можно порекомендовать специализированный редактор CSS, который позволяет кодировать вручную или использовать удобный интерфейс. Это редактор StyleMaster, информацию о котором можно найти в Internet по ссылке www.westciv.com/style_master
Не будем использовать созданную оболочкой заготовку StyleSheet.css,
а научимся подключать к
странице через оболочку свою уже готовую
Удалите
созданную оболочкой заготовку StyleSheet.css
Создайте
копию статической страницы Page3.htm и
присвойте копии имя Page4.htm
Назначьте
страницу Page4.htm стартовой (команда Set
As Start Page ) и запустите ее на выполнение, чтобы
убедиться в ее работоспособностиЕсли страница не содержит серверных элементов с атрибутом runat="server", то система ASP.NET
просто отсылает клиенту код этой страницы в неизменном
виде. Если посмотреть на исходный HTML-код присланной броузеру
страницы (команда View
Source контекстного
меню окна броузера), то он остался тем же самым, что и в генерирующей
странице Page4.htm
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Документ со встроенной CSS</title>
<meta content="text/html; charset=windows-1251" http-equiv="Content-Type">
<link href="ExternalCSS.css" rel="stylesheet">
</head>
<body>
<h1>
Заполните анкету!
</h1>
<form id="form1" action="Page3.htm">
<p>
Введите ФИО:
<input id="TextBox1" name="TextBox1" type="text">
</p>
<p>
Введите ИНН:
<input id="TextBox2" name="TextBox2" type="text">
</p>
<center>
<input id="Button1" class="btnResult" name="Button1"
type="button" value="Отослать">
</center>
</form>
</body>
</html>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Документ со встроенной CSS</title>
<meta content="text/html; charset=windows-1251" http-equiv="Content-Type">
<link href="ExternalCSS.css" rel="stylesheet">
</head>
<body>
<h1>
Заполните анкету!
</h1>
<form id="form1" action="Page4.htm">
<p>
Введите ФИО:
<input id="TextBox1" name="TextBox1" type="text">
</p>
<p>
Введите ИНН:
<input id="TextBox2" name="TextBox2" type="text">
</p>
<center>
<input id="Button1" class="btnResult" name="Button1"
type="button" value="Отослать">
</center>
</form>
</body>
</html>
Отвлечемся немного от темы стилей и обратим внимание на то, сколько строк нашего кода возможно подчеркнул редактор оболочки красной линией. Это значит, что его не устраивает синтаксис кода, на проверку которого он настроен.

Чтобы успокоить редактор, нужно сообщить ему, чтобы он проверял синтакис чистого HTML, а не XHTML.
Выполните
команду Tools/Customize и отметьте флажок HTML Source Editing
В верхней части каркаса оболочки появится панель инструментов
настройки HTML-редактора, в которой нужно установить через
раскрывающийся список опцию HTML
4.01. Через некоторое время,
после очередного сканирования синтаксиса документа <form>.
Чтобы избавиться и от этого замечания редактора, нужно добавить
атрибут action с целевой страницей, которая
будет обрабатывать обратную отсылку (постинг) на сервер, в нашем
случае
<form action="Page4.htm">
Посмотрите, как и в этом случае нам услужливо помогает подсказчик
кода , предлагающий выбрать
из списка файлов целевую страницу на сервере, которая будет принимать
данные от формы

Вообще-то, большинство броузеров при пропущенном атрибуте action полагают,
что целевой будет та же самая страница.
Но чтобы успокоить HTML редактор окончательно, укажем эту страницу
явно.
Вызовите
контекстное меню щелчком правой кнопки мыши на свободном
месте верхней части каркаса оболочки и сбросьте флажок HTML
Source Editing, чтобы закрыть одноименную панель
настройки редактора
Удалите
из заголовочного блока страницы Page4.htm код
подключения внешней <link rel="stylesheet" href="ExternalCSS.css">
Переведите
страницу в режим Design и посмотрите, какая
она сразу стала некрасивая
Вернитесь
в режим Source и убедитесь, что оболочка
добавила нужный дескриптор подключения CSS в
нужное место
Опять
удалите дескриптор подключения CSS
Перейдите
в режим Design, откройте панель Properties и
через раскрывающийся список в ее верхней части выберите объект DOCUMENT
Найдите
свойство StyleSheet и подключите к нему
таблицу ExternalCSS.css через диалоговое
окно. Оболочка опять добавит нужный дескриптор подключения CSS в
нужное место
Очистите
поле свойства StyleSheet, оболочка вновь
удалит дескриптор подключенияТаблицы CSS применяются не только к простым
дескрипторам HTML,
но и к дескрипторам Label.
Откройте
панель ToolboxМы видим, что доступной является только вкладка HTML, потому, что наша тестовая страница Page4.htm имеет расширение .htm.
Измените
в панели Solution Explorer расширение страницы
на Page4.aspx и
сделайте страницу принимающей, исправив дескриптор <form><form action="Page4.aspx"
runat="server">
Вкладка Standard в панели Toolbox все равно не появилась, потому что редактор оболочки все еще считает страницу статической.
Для
изменения мнения редактора о типе страницы закройте редактирование
страницы Page4.aspx, затем вновь откройте
Поместите
на страницу между текстовым
полем и кнопкой из вкладки Standard текстовую
метку Label и
в панели Properties определитеCssClass=labelText=Стиль
класса label
Откройте
через Solution Explorer файл ExternalCSS.css и
добавьте стилевое правило для класса label .label
{
background-color:Green;
color:White;
font:bold;
font-size:x-large;
font-family:Courier New;
}
body
{
background:white url(Web.jpg);
font-family:Arial, Helvetica, sans-serif;
}
h1
{
color:#FF0000;
text-align:center;
}
#TextBox1
{
font-family:"Courier New", Courier, mono;
font-size:24px;
font:bold italic;
background-color:#0000FF;
color:yellow;
width:400;
}
.btnResult
{
background-image:url(BackgroundImage.bmp);
color:white;
}
Переведите
страницу в режим Design,
Выполните
страницу, которая
в броузере станет такой
Краткое знакомство с CSS и их поддержкой в Visual Studio 2005 закончили!
Применение CSS для стилевого оформления страниц ASP.NET имеет некоторые ограничения. Дело в том, что CSS являются решением стороны броузера. Они оформляют уже готовые дескрипторы HTML, поступившие на броузер. Если их бездумно применять на стороне сервера к элементам управления, которые могут генерировать для отправки клиенту целый пакет HTML-дескрипторов, то конечное стилевое оформление может не в полной мере соответствовать желаниям разработчика. Для таких ситуаций существуют другие средства форматирования, которые являются родным решением элементов управления на стороне сервера и позволяют полностью контролировать их стилевое оформление. Одним из таких средств являются темы.
Как и CSS, темы определяют набор стилей, которые называют оформлениями и которые можно применять на многих страницах ASP.NET. Особенности тем состоят в следующем:
http://
www.asp.net. Но если тема используется, то
для обеспечения гибкости и автономности она должна физически
находиться в каталоге приложения.Все темы помещаются в каталог с зарезервированным именем App_Themes,
который можно добавить к приложению в панели Solution
Explorer,
выполнив команду Add ASP.NET Folder/Theme контекстного
меню для узла приложения
Каждая тема должна храниться в своей одноименной папке и может
состоять из нескольких файлов

Папку App_Themes отдельно можно и не создавать, потому, что при попытке добавления нового файла типа Skin File оболочка предложит автоматически создать папку App_Themes

Для темы можно все стилевые настройки элементов управления разместить в одном файле оформленийscin, а можно и в нескольких. Иногда просто удобнее группировать оформления по отдельным категориям элементов управления в соответствующих файлах. Для ASP.NET это не имеет никакого значения, поскольку она все равно считывает все файлы оформлений в каталоге указанной темы как неделимое целое определения одной темы.
Структура папки App_Themes может иметь следующий вид

Проверим сказанное на практике.
Добавьте
к проекту новую страницу Page5.aspx с
отделенным кодом
Добавьте
на страницу из вкладки Standard следующие
элементы управленияBulletedListLabelCheckBox Button
Назначьте
свойства Text этих элементов (для BulletedList - коллекция Items ) и
скомпонуйте их на странице так, чтобы их внешний вид
на этапе проектирования был следующим
В панели Solution Explorer создайте копию файла Page5.aspx и
присвойте ей имя FirstSkin.aspx.
Из него мы в дальнейшем сделаем файл оформлений
Удалите
файл кодовой поддержки FirstSkin.aspx.cs
Настройте
декларативно в панели Properties стилевые свойства объектов
страницы FirstSkin.aspx| Элемент | Свойство | Значение |
|---|---|---|
BulletedList |
ID |
BulletedList1 |
|
BackColor |
Yellow |
|
BorderColor |
Red |
|
BorderStyle |
|
|
|
10px |
|
BulletStyle |
Numbered |
|
ForeColor |
Blue |
Label |
ID |
Label1 |
|
BackColor |
Blue |
|
ForeColor |
Yellow |
|
|
Текстовая метка |
|
ID |
CheckBox1 |
|
BackColor |
Red |
|
BorderStyle |
|
|
Font/Bold |
True |
|
ForeColor |
White |
Button |
ID |
Button1 |
|
BackColor |
#FFC0C0 |
|
BorderColor |
Blue |
|
BorderStyle |
|
|
|
2px |
|
Font/Bold |
True |
|
ForeColor |
Blue |
Внешний вид элементов управления после проведенных стилевых настроек должен быть таким

Перейдите
в режим Source и удалите из файла FirstSkin.aspx весь
код, кроме открывающих дескрипторов элементов управления, в
которых тоже удалите атрибуты, не относящиеся к настройкам
стиля, включая атрибут IDВ файле FirstSkin.aspx должно остаться следующее
<asp:BulletedList runat="server"
BackColor="Yellow" BorderColor="Red"
BorderStyle="Ridge" BorderWidth="10px"
BulletStyle="Numbered" ForeColor="Blue" />
<asp:Label runat="server"
BackColor="Blue" ForeColor="Yellow"
ToolTip="Текстовая метка" />
<asp:CheckBox runat="server"
BackColor="Red" BorderStyle="Groove"
Font-Bold="True" ForeColor="White" />
<asp:Button runat="server"
BackColor="#FFC0C0" BorderColor="Blue"
BorderStyle="Solid" BorderWidth="2px"
Font-Bold="True" ForeColor="Blue" />
Присвойте
файлу FirstSkin.aspx новое расширение FirstSkin.skin
Создайте
в приложении папку с зарезервированным именем App_Themes и
определите в ней подпапку с именем MyTheme,
в которой будут храниться файлы оформлений этого
упражнения (точнее, будет всего один файл FirstSkin.skin )
В панели Solution
Explorer Тема подключается к странице с помощью атрибута директивы @Page. Так, например, при применении темы
с именем каталога MyTheme к странице упражнения Page5.aspx директива
будет выглядеть так
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="Page5.aspx.cs" Inherits="Page5"
Theme="MyTheme" %>
Тему можно подключить к странице и в панели Properties через
свойство объекта DOCUMENT.
В этом случае оболочка автоматически добавит атрибут к
директиве @Page с выбранным значением.
В раскрывающемся
списке панели Properties для
страницы Page5.aspx выделите объект DOCUMENT и
установите свойство Theme ="MyTheme"
Назначьте
страницу Page5.aspx стартовой и выполните
ееПредставление рендеринга на стороне клиента, сгенерированного активной страницей Page5.aspx, с учетом присоединенных через тему стилевых настроек элементов управления будет иметь вид

Естественно, что переопределяются только те стилевые настройки элементов управления страницы, которые указаны в подключенной теме. Остальные настройки не переопределяются.
При подключении CSS стили
начинают действовать на отображение элементов немедленно, на
этапе проектирования и мы можем их подбирать, сразу видя результат.
При определении свойства действие
стилей мы увидим только на этапе выполнения. Механизм тем реализует
стилевые способности генерирующих элементов управления только
при выполнении в соответствии с настройками, хранящимися отдельно
в одном или нескольких файлах оформлений каталога темы.
Элементы управления страницы могут иметь свои индивидуальные стилевые настройки, которые мы им декларативно назначим при разработке страницы. Но если элемент на странице имеет настройки, которые дублируются в теме, то приоритет будут иметь одноименные настройки, указанные в подключаемой теме. Проверим это...
В панели Solution Explorer получите копию страницы Page5.aspx и
присвойте ей имя Page6.aspx
Установите
прямо в настройках страницы Page6.aspx для
элемента CheckBox1 атрибутыBackColor="Black"ForeColor="Yellow"Мы хотим,
чтобы элемент CheckBox1 имел черный фон
и желтый текст, т.е. ждем его таким

Выполните
страницу и убедитесь, что элемент CheckBox1 попрежнему
будет иметь цвет фона красный, а Theme ="MyTheme" Объект DOCUMENT страницы
имеет еще одно свойство StyleSheetTheme, к
которому также можно подключить внешнюю тему. В этом случае
приоритет будут иметь индивидуальные настройки элементов управления,
которые в них были явно определены. Но те настройки по умолчанию,
которые мы не определяли на странице, но которые содержатся
в теме, на свойства по умолчанию действуют.

Для
страницы Page6.aspx в панели Properties выделите
объект DOCUMENT, очистите поле его свойства Theme и
подключите тему MyTheme к свойству StyleSheetTheme
Выполните
страницу и убедитесь, что индивидуальная настройка элемента CheckBox1 имеет
приоритетEnableTheming="False".
Влияние настроек темы на всю страницу можно отключить,
если в директиве @Page страницы установить
атрибут EnableTheming="False" (по
умолчанию это свойство страницы имеет значение True ).
Для
страницы Page6.aspx в панели Properties выделите объект DOCUMENT,
очистите поле его свойства StyleSheetTheme и
подключите тему MyTheme к свойству Theme
Выделите
объект CheckBox1 с индивидуальными настройками BackColor="Black" ; ForeColor="Yellow" и
отключите для него влияние темы EnableTheming="False"
Выполните
страницу и убедитесь, что настройки темы отключены и действуют
только настройки по умолчанию и индивидуальные настройки
элемента
Выделите
объект CheckBox1 и верните
для него EnableTheming="True"Стилевые настройки, которые мы до сих пор определяли в файле оформлений темы, являются настройками
по умолчанию и
применяются для всех элементов управления
Если просто определить в теме несколько
вариантов настроек для одного и того же элемента управления,
то ASP.NET выдаст ошибку об обнаружении неоднозначности.
В этом случае в теме нужно применять именованные
оформления с помощью атрибута SkinID. Стиль элемента управления в файле
оформлений будет иметь метку SkinID, и на странице наряду
с общим подключением темы с помощью свойства нужно
будет определить дополнительные свойства SkinID для
отдельных элементов управления.
Значения SkinID в определениях темы должно
быть уникальным только в группе однотипных элементов. Это значит,
что мы можем создать несколько групп настроек разнотипных элементов
с одинаковыми значениями атрибута SkinID и
подключать из одной темы, по мере необходимости, к каждому
элементу управления свои индивидуальные настройки.
Скопируйте
страницу Page5.aspx в страницу Page7.aspx
Добавьте
в страницу Page7.aspx элемент Table из
вкладки HTML панели Toolbox. Таблицу расположите между кнопкой
и Для нашего упражнения таблица должна иметь три столбца и пять строк. Оболочка не обладает развитыми средствами редактирования таблиц, поэтому проще настроить таблицу в режиме Source.
Поместите
из вкладки Standard панели Toolbox в
средний столбец таблицы пять серверных элементов Label,
а в правый - пять серверных элементов CheckBox SkinID не подключен: действуют общие настройки
по умолчанию |
Label2 |
![]() |
Именованные настройки подключены: SkinID="Variant3" |
Label3 |
![]() |
Именованные настройки подключены: SkinID="Variant4" |
Label4 |
![]() |
SkinID="Variant5" подключен, но тема подавлена: EnableTheming="False" |
Label5 |
![]() |
Подключен несуществующий SkinID="XXX": настройки темы
не действуют |
Label6 |
![]() |
В панели Solution Explorer щелкните на узле MyTheme и
добавьте к проекту новый файл оформлений с именем FirstSkinID.skin 
Очистите
от комментариев файл
оформленийFirstSkinID.skin и
дополните его индивидуальными именованными настройками
стилей, чтобы общий код его стал таким<asp:Label runat="server" BackColor="Blue" ForeColor="Yellow" SkinID="Variant2" />
<asp:CheckBox runat="server" BackColor="Red" BorderStyle="Groove"
Font-Bold="True" ForeColor="White" SkinID="Variant2" />
<asp:Label runat="server" ForeColor="Blue" SkinID="Variant3" />
<asp:CheckBox runat="server" BorderStyle="Dotted" Font-Bold="True"
ForeColor="Red" SkinID="Variant3" />
<asp:Label runat="server" BackColor="Yellow" ForeColor="Red" SkinID="Variant4" />
<asp:CheckBox runat="server" BackColor="Red" BorderStyle="Solid"
ForeColor="Yellow" SkinID="Variant4" />
<asp:Label runat="server" BackColor="Blue" ForeColor="Yellow" SkinID="Variant5" />
<asp:CheckBox runat="server" BackColor="Red" BorderStyle="Groove"
Font-Bold="True" ForeColor="White" SkinID="Variant5" />
<asp:Label runat="server" BackColor="Blue" ForeColor="Yellow" SkinID="Variant6" />
<asp:CheckBox runat="server" BackColor="Red" BorderStyle="Groove"
Font-Bold="True" ForeColor="White" SkinID="Variant6" />
Установите
в добавленных объектах свойство SkinID в
соответствии с первым столбцом компоновочной таблицы, приведенной
ранее
Выполните
страницу Page7.aspx, результат должен быть примерно таким
Вспомним, что активизируются все файлы оформлений, соответствующие указанной теме и расположенные в соответствующем одноименном каталоге. И в нашем упражнении часть элементов страницы оформляется с помощью неименованных атрибутов, расположенных в файле App_Themes\MyTheme\ FirstSkin.skin, а часть - с помощью именованных, расположенных в файле App_Themes\MyTheme\ FirstSkinID.skin.
Можно сделать все стилевые оформления именованными.
В этом случае, если в элементах управления на странице не
будет задан атрибут SkinID,
то эти именованные стилевые настройки никогда не будут применяться.
Окончательный код интерфейсной части страницы Page7.aspx будет следующим
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="Page7.aspx.cs" Inherits="Page7"
Theme="MyTheme" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:BulletedList ID="BulletedList1" runat="server">
<asp:ListItem>Туризм</asp:ListItem>
<asp:ListItem>Спорт</asp:ListItem>
<asp:ListItem>Музыка</asp:ListItem>
<asp:ListItem Value="Танцы"></asp:ListItem>
</asp:BulletedList>
<asp:Label ID="Label1" runat="server" Text="Текстовая метка"></asp:Label>
<asp:CheckBox ID="CheckBox1" runat="server" Text="Флажок" />
<br />
<br />
<table bgcolor="#FFFFFF">
<tr>
<td>
SkinID не подключен: действуют общие настройки по умолчанию
</td>
<td>
<asp:Label ID="Label2" runat="server" Text="Label2"></asp:Label></td>
<td style="height: 26px">
<asp:CheckBox ID="CheckBox2" runat="server" Text="CheckBox2" /></td>
</tr>
<tr>
<td>
Именованные настройки подключены: SkinID="Variant3"</td>
<td>
<asp:Label ID="Label3" runat="server" SkinID="Variant3" Text="Label3"></asp:Label></td>
<td>
<asp:CheckBox ID="CheckBox3" runat="server" SkinID="Variant3" Text="CheckBox3" /></td>
</tr>
<tr>
<td>
Именованные настройки подключены: SkinID="Variant4"</td>
<td>
<asp:Label ID="Label4" runat="server" SkinID="Variant4" Text="Label4"></asp:Label></td>
<td>
<asp:CheckBox ID="CheckBox4" runat="server" SkinID="Variant4" Text="CheckBox4" /></td>
</tr>
<tr>
<td>
SkinID="Variant5" подключен, но тема подавлена: EnableTheming="False"</td>
<td>
<asp:Label ID="Label5" runat="server" EnableTheming="False" SkinID="Variant5"
Text="Label5"></asp:Label></td>
<td>
<asp:CheckBox ID="CheckBox5" runat="server" EnableTheming="False" SkinID="Variant5"
Text="CheckBox5" /></td>
</tr>
<tr>
<td>
Подключен несуществующий SkinID="XXX": настройки темы не действуют</td>
<td>
<asp:Label ID="Label6" runat="server" SkinID="XXX" Text="Label6"></asp:Label></td>
<td>
<asp:CheckBox ID="CheckBox6" runat="server" SkinID="XXX" Text="CheckBox6" /></td>
</tr>
</table>
<br />
<asp:Button ID="Button1" runat="server" Text="Отправить" />
</div>
</form>
</body>
</html>
Сложные элементы управления включают в себя несколько разделов, требующих индивидуальных стилевых оформлений. Эти настройки могут занимать много места, если их использовать вместе с дескрипторным кодом в интерфейсной части страницы. Поэтому для таких элементов выносить громоздкий код стилевых настроек в отдельный файл оформлений очень даже удобно. Приведем пример с настройками элемента Calendar.
Создайте
новую страницу со встроенным кодом поддержки и с именем Page8.aspx
Назначьте
страницу стартовой и поместите на нее из вкладки Standard элемент
управления Calendar
Определите
для объекта Calendar1 следующие стилевые
настройки<asp:Calendar ID="Calendar1" runat="server"
BackColor="white" ForeColor="black" BorderColor="black"
BorderStyle="solid" CellSpacing="1" Font-Names="Vernada"
Font-Size="9pt" Height="250px" Width="500px"
NextPrevFormat="ShortMonth" SelectionMode="day">
<SelectedDayStyle BackColor="darkorange" ForeColor="white" />
<DayStyle BackColor="orange" Font-Bold="true" ForeColor="white" />
<NextPrevStyle Font-Bold="true" Font-Size="8pt" ForeColor="white" />
<DayHeaderStyle Font-Bold="true" Font-Size="8pt"
ForeColor="#333333" Height="8pt" />
<TitleStyle BackColor="firebrick" BorderStyle="none"
Font-Bold="true" Font-Size="12pt"
ForeColor="white" Height="12pt" />
<OtherMonthDayStyle BackColor="navajowhite"
Font-Bold="false" ForeColor="darkgray" />
</asp:Calendar>
В панели Solution Explorer вызовите контекстное меню
для папки MyTheme и командой Add
New Item создайте новый файл оформлений с
именем Calendar.skin
Запомните,
как пишутся комментарии в интерфейсных файлах ASP.NET и
очистите автоматически сгенерированный текст в файле
оформленийCalendar.skin
Скопируйте
из страницы Page8.aspx в файл оформленийCalendar.skin весь
дескрипторный код объекта Calendar1 вместе
с его стилевыми настройками и
удалите в копии атрибут ID="Calendar1",
оставив только атрибуты стилевых настроек<asp:Calendar runat="server"
BackColor="white" ForeColor="black" BorderColor="black"
BorderStyle="solid" CellSpacing="1" Font-Names="Vernada"
Font-Size="9pt" Height="250px" Width="500px"
NextPrevFormat="ShortMonth" SelectionMode="day" >
<SelectedDayStyle BackColor="darkorange" ForeColor="white" />
<DayStyle BackColor="orange" Font-Bold="true" ForeColor="white" />
<NextPrevStyle Font-Bold="true" Font-Size="8pt" ForeColor="white" />
<DayHeaderStyle Font-Bold="true" Font-Size="8pt" ForeColor="#333333" Height="8pt" />
<TitleStyle BackColor="firebrick" BorderStyle="none" Font-Bold="true"
Font-Size="12pt" ForeColor="white" Height="12pt" />
<OtherMonthDayStyle BackColor="navajowhite" Font-Bold="false" ForeColor="darkgray" />
</asp:Calendar>
Удалите
в дескрипторном коде страницы Page8.aspx код
стилевых настроек объекта Calendar1, чтобы
от объекта осталось только простое описание<asp:Calendar ID="Calendar1" runat="server">
</asp:Calendar>
Через
панель Properties выделите объект DOCUMENT и поключите
к странице тему MyTheme в свойстве Theme
Выполните
страницу и убедитесь, что вынесенный со страницы в тему большой
блок стилевых настроек элемента Calendar работает
также, как если бы он находился на самой страницеНиже приведены два варианта представления объекта Calendar1: без темы и с подключенной темой
![]() |
![]() |
| Тема с настройками не подключена | Внешние стилевые настройки работают |
|---|
С помощью внешних файлов оформлений и тем можно подключать
стилевые компоненты рисунков. Пусть мы хотим использовать несколько
кнопок элемента управления с разными
рисунками в зависимости от контекста применения. Пусть для
кнопок OK будет использован один рисунок,
а для кнопок - другой. Темы позволяют
легко решить эту задачу.
В
панели Solution Explorer через контекстное
меню на папке MyTheme командой New Folder создайте
подпапку ButtonImages для
хранения рисунков кнопок
В
панели Solution Explorer через контекстное
меню на новой папке ButtonImages командой Add Existing Item вызовите диалоговое окно
копирования и из прилагаемого каталога Source скопируйте
рисунки ButtonCancel.png и ButtonOK.png
Создайте
из страницы Page8.aspx копию с именем Page9.aspx и
назначьте ее стартовой
Добавьте
на страницу Page9.aspx из вкладки Standard панели Toolbox две
кнопки типа ImageButton и
настройте через одноименные свойства в панели Properties их
дескрипторы так<asp:ImageButton ID="ImageButton1" runat="server"
ImageUrl="~/App_Themes/MyTheme/ButtonImages/ButtonOK.png"
SkinID="OKButton" />
<asp:ImageButton ID="ImageButton2" runat="server"
ImageUrl="~/App_Themes/MyTheme/ButtonImages/ButtonCancel.png"
SkinID="CancelButton" />
В контекстном
меню на папке MyTheme выполните команду Add
New Item, чтобы добавить в тему новый файл оформленияButtons.skin
Скопируйте
настроенные дескрипторы элементов ImageButton в
файл Buttons.skin, предварительно очистив
его от автоматически сгенерированных инструкций
Удалите
из файла оформлений Buttons.skin атрибуты ID, чтобы код стал выглядеть так<asp:ImageButton runat="server"
ImageUrl="ButtonImages/ButtonOK.png"
SkinID="OKButton" />
<asp:ImageButton runat="server"
ImageUrl="ButtonImages/ButtonCancel.png"
SkinID="CancelButton" />
Обратите внимание, что мы в атрибуте ImageUrl указали
путь только относительно каталога темы. Путь до корня виртуального
каталога сайта " ~/App_Themes/MyTheme/ " добавит ASP.NET при компиляции этого кода и автоматически
преобразует его в абсолютный путь файловой системы сервера.
Откорректируйте
дескрипторы ImageButton в файле Page9.aspx,
чтобы от них осталось только следующее<asp:ImageButton ID="ImageButton1" runat="server" SkinID="OKButton" /> <asp:ImageButton ID="ImageButton2" runat="server" SkinID="CancelButton" />
Исполните
страницу Page9.aspx и получите следующий
результат с внешними оформлениями в темах сложного календаря
и рисуночных кнопок
На интерфейсной странице находится дескрипторный код только создания сложных элементов управления, а большой код тонких настроек вынесен в файлы темы. Это очень удобно и для централизованного изменения стилевого оформления элементов управления, и для читабельности самой страницы.
Если у нас имеются хорошие наработки CSS, то ASP.NET позволяет использовать их для форматирования HTML-дескрипторов активной страницы. Чтобы подключить CSS к активной странице, нужно сделать следующее:
CSS в каталог
темыTheme объекта DOCUMENT страницыCSS содержит классы, подключить
их в свойстве CssClass элементов
управления страницы<link>, используемого
при традиционном способе подключения к странице, проследить,
чтобы заголовочный дескриптор страницы был объявлен как серверный
( <head runat="server"> ).
В этом случае ASP.NET сама при запросах
страницы будет генерировать столько дескрипторов <link> в
выходном HTML-коде, сколько файлов CSS будет
находиться в подключенной к странице темеПроверим сказанное. В панели Solution Explorer оболочки выполните следующие действия:
Скопируйте
файл Page4.aspx, присвойте копии имя Page10.aspx и
назначьте новую страницу стартовой
Откройте
файл Page5.aspx, скопируйте из него на страницу Page10.aspx (ниже
кнопки) интерфейсный код BulletedList, Label, CheckBox После этого вид страницы Page10.aspx без стилевого оформления на этапе проектирования должен быть таким

Скопируйте таблицу
стилей ExternalCSS.css в
папку MyTheme проекта.
Копирование выполните в панели Solution Explorer так:
щелкните правой кнопкой мыши на файле ExternalCSS.css и
выполните команду Copy, затем щелкните правой
кнопкой мыши на папке MyTheme и выполните
команду Paste. Назначьте копии
имя ThemeCSS.css
Подобным
же образом скопируйте из каталога Resources в
каталог MyTheme два
файла BackgroundImage.bmp и Web.jpg,
чтобы они оказались в одном каталоге с файлом ThemeCSS.css
Откройте
страницу Page10.aspx на редактирование,
удалите в ней дескриптор <link> подключения
внешней <head> атрибут runat="server",
чтобы он стал обрабатываться средой ASP.NET
Откройте
файл ThemeCSS.css и замените
url( |
---> |
url(Web. |
url( |
---> |
url(BackgroundImage. |
Подключить
тему MyTheme к
странице Page10.aspx, добавив в самое ее
начало директиву<%@ Page Language="C#"
Выполните
страницу Page10.aspx и убедитесь, что
стили из внешней таблицы ThemeCSS.css работаютРезультат выполнения страницы будет таким

На данной странице Page10.aspx <link> ссылку
на внешнюю CSS.
Броузер, получив ссылку на внешнюю CSS,
проверяет в соответствии с правилом приоритета стилей возможность
их применения только в тех дескрипторах HTML, в которых
нет своих внутренних стилей, сгенерированных серовером на
основании темы.
Иными словами
Теперь осталось проверить тот факт, что ASP.NET подключает
к странице все
В каталоге Theme сделайте еще три копии файла ThemeCSS.css с
именем ThemeCSS1.css, ThemeCSS2.css, ThemeCSS3.css
Выполните
страницу Page10.aspx и в появившемся окне броузера выполните
команду контекстного меню View Source для
присланной с сервера страницы-откликаИсследуем блок кода заголовочного дескриптора <head>. Он будет содержать такие строки
<head>
<title>Документ с внешней CSS</title>
<meta content="text/html; charset=windows-1251" http-equiv="Content-Type" />
<link href="App_Themes/MyTheme/ThemeCSS.css" type="text/css" rel="stylesheet" />
<link href="App_Themes/MyTheme/ThemeCSS1.css" type="text/css" rel="stylesheet" />
<link href="App_Themes/MyTheme/ThemeCSS2.css" type="text/css" rel="stylesheet" />
<link href="App_Themes/MyTheme/ThemeCSS3.css" type="text/css" rel="stylesheet" />
</head>
Мы видим, что среда исполнения ASP.NET автоматически вставляет в код столько дескрипторов подключения CSS, сколько файлов с таблицами находится в каталоге темы. Обратите внимание, что пути в ссылках прописываются относительно корня виртуального каталога, в котором находится сама страница.
Удалите
лишние файлы ThemeCSS1.css, ThemeCSS2.css и ThemeCSS3.cssДо сих пор мы спокойно удаляли файл web.config приложения с уверенностью, что он будет вновь создан оболочкой. Тем более, что там содержалась только заготовка кода. Теперь пришла пора редактировать этот файл и удалять его уже будет жалко.
Ранее мы говорили, что при подключении к странице темы (в
наших примерах - MyTheme ) через свойство объекта DOCUMENT оболочка
автоматически вставляет соответствующий атрибут в директиву @Page этой страницы, тем самым подключая к
странице индивидуальную тему.
Например
<% @Page Language="C#" Theme="MyTheme" %>
Обычно проектировщики ратуют за одинаковое стилевое оформление
страниц и используют в каждой из них одну и ту же тему. В этом
случае удобнее будет не подключать каждую страницу к одной
и той же теме, а указать общую тему в
Откройте
страницы наших примеров, использующих темы, а именно: Page5.aspx, Page8.aspx, Page10.aspx,
и скопируйте их в файлы с именами TestTheme.aspx, TestCalendar.aspx, ThemeCSS.aspx соответственно
Удалите
в них из директивы @Page атрибут Theme ="MyTheme"
Вызывая
для каждой страницы контекстное меню и выполняя команду View in Browser,
исполните их по очереди, чтобы убедиться, что отключенная
тема в них не действует. Пока получилась грустная, унылая
картина
Откройте
на редактирование файл web.config и добавьте
в секцию <system.web> дескриптор
с указанием общей темы<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true"/>
<authentication mode="Windows"/>
<pages theme="MyTheme" />
</system.web>
</configuration>
Вновь
выполняя для каждой страницы команду View in Browser,
исполните файлы по очереди, чтобы убедиться, что тема
опять заработала так, как будто-бы она была индивидуально
подключена к каждой страницеЕсли нужно сделать так, чтобы общая тема действовала по умолчанию на множестве страниц, но не перезаписывала на них индивидуальные стилевые настройки элементов управления, то конфигурационный файл должен быть таким
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true"/>
<authentication mode="Windows"/>
<pages styleSheetTheme="MyTheme" />
</system.web>
</configuration>
Если на какой-нибудь странице нужно сделать так, чтобы общая тема не действовала на нее по умолчанию, то есть два варианта:
@Page атрибут Theme =" Другая_тема "@Page страницы нужно
вставить атрибут EnableTheming="false"CSS дескриптором <link> или
в CSS,
то отключение темы по умолчанию атрибутом EnableTheming="false" отключает
только skin -файлы, CSS все
равно останется подключенной.Во всех наших примерах мы создавали активные страницы в корневом виртуальном каталоге сайта. Но для сайта с тысячами страниц это неприемлемый способ. Страницы могут группироваться по любому признаку, например тематическому, и размещаться в отдельных папках развитой древовидной системы виртуальных каталогов. Корнем этого дерева должен быть виртуальный каталог сайта, его еще называют корнем Web-дерева.
В развитом Web-дереве применение общей темы по умолчанию является удобным способом стилизации страниц. В каждом каталоге можно разместить отдельный файл web.config со своей общей темой и все страницы этого каталога будут использовать эту тему по умолчанию.
До сих пор мы рассматривали случай, когда разработчик сам
жестко привязывает тему к странице или группе страниц. Но иногда
может возникнуть необходимость поручить выбор
темы для конкретной страницы пользователю с немедленным изменением
ее стилевого оформления. При этом неважно, была ли включена
на странице индивидуальная тема или по умолчанию применялась
тема
Все,
что нужно сделать, это предусмотреть на странице интерфейс
выбора темы, а в коде страницы динамически присвоить свойству Page. или Page.StyleSheetTheme выбранное пользователем
значение. При этом важно понимать, что тема настраивается
перед инициализацией страницы, поэтому соответствующий код
нужно поместить в обработчик Page_PreInit(). Если это сделать
позже, в обработчиках других событий, то попытка присвоить
новое значение свойству Page. или Page.StyleSheetTheme вызовет ошибку компиляции.
С другой стороны, прочитать выбор пользователя можно только после создания страницы, когда присваивать свойству темы новое значение уже поздно. Поэтому динамическое задание темы нужно выполнять в два этапа:
Page_PreInit() назначить новую темуПри перезапуске страницы она должна быть переадресована на
саму себя. Такую операцию можно выполнить либо
методом Response., либо
методом Server..
Первый метод реализует полный
цикл с
отправкой на броузер и автоматическим возвращением на сервер.
Он тратит лишнее
время на пересылку.
Второй метод перезапускает страницу сразу на сервере без цикла
через клиента. Но есть одна существенная особенность: оба метода сбрасывают состояние
вида всех элементов управления и запускают страницу как в при
первом запросе.
Поскольку выбирать не из чего, то мы применим
второй метод Server..
Рассмотрим все это на примере. Прежде всего, нужно создать несколько тем, чтобы было из чего пользователю выбирать.
В панели Sulution Explorer вызовите контекстное меню для папки MyTheme и выполните команду Copy
В панели Sulution Explorer вызовите контекстное меню
для папки App_Themes, где должны храниться
все темы приложения, и выполните на ней команду Paste два
раза, чтобы создать еще две темы
Присвойте
копиям имена, например, MyTheme1 и MyTheme2Обратите внимание, что новые темы имеют старое содержание, которое было-бы желательно подправить, чтобы наглядно видеть влияние выбранной темы на оформление страницы. Мы это сделаем попозже.
Учитывая, что протокол HTTP не поддерживает
сохранение состояний и что страница существует только на время
обработки обратной отсылки, выбранную пользователем тему нужно
где-то сохранять. Это могут быть -наборы
( куки -файлы) на компьютере клиента,
которые мы туда запишем без его ведома, если он забыл выключить
их поддержку. Это могут быть Session.
Через
панель Solution Explorer скопируйте в корневой
виртуальный каталог нашего сайта файл TestTheme.aspx и
назовите его TestSwitchThemes.aspx
Определите
новую страницу TestSwitchThemes.aspx стартовой
Откройте
файл TestSwitchThemes.aspx на редактирование
и добавьте в верхнюю часть страницы из
вкладки Standard элемент
списока DropDownList для выбора темы
Переименуйте ID списка в lstSwitchThemes
Через
панель Properties в режиме Events создайте
для списка заготовку обработчика события SelectedIndexChanged,
которое поступит на сервер с обратной отсылкой, если пользователь
изменит выбор в списке
Добавьте
на страницу перед списком серверный элемент Label с
именем lblFirstLoadИнтерфейсная часть страницы TestSwitchThemes.aspx примет следующий вид

Код интерфейсной части страницы TestSwitchThemes.aspx следующий
<%@ Page AutoEventWireup="true" CodeFile="TestSwitchThemes.aspx.cs"
Inherits="TestSwitchThemes" 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>
<asp:Label ID="lblFirstLoad" runat="server" Text="Label"></asp:Label>
<br />
<asp:DropDownList ID="lstSwitchThemes" runat="server"
OnSelectedIndexChanged="lstSwitchThemes_SelectedIndexChanged">
</asp:DropDownList>
<br />
<asp:BulletedList ID="BulletedList1" runat="server">
<asp:ListItem>Туризм</asp:ListItem>
<asp:ListItem>Спорт</asp:ListItem>
<asp:ListItem>Музыка</asp:ListItem>
<asp:ListItem Value="Танцы"></asp:ListItem>
</asp:BulletedList>
<asp:Label ID="Label1" runat="server" Text="Текстовая метка"></asp:Label>
<asp:CheckBox ID="CheckBox1" runat="server" Text="Флажок" /><br />
<br />
<asp:Button ID="Button1" runat="server" Text="Отправить" /></div>
</form>
</body>
</html>
Откройте
на редактирование файл кода TestSwitchThemes.aspx.cs и заполните
его такusing System;
public partial class TestSwitchThemes : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
lblFirstLoad.Text = "Первая загрузка страницы";
// Заполняем список именами каталогов тем
System.IO.DirectoryInfo themeDir =
new System.IO.DirectoryInfo(Server.MapPath("App_Themes"));
lstSwitchThemes.DataTextField = "Name";
lstSwitchThemes.DataSource = themeDir.GetDirectories();
lstSwitchThemes.DataBind();
}
else
lblFirstLoad.Text = "Повторная загрузка страницы";
}
protected void Page_PreInit(object sender, EventArgs e)
{
if (Session["Theme"] != null)
{
// Был ранее сохраненный выбор, включить его
Page.Theme = (string)Session["Theme"];
// Восстанавливаем новое состояние списка
lstSwitchThemes.SelectedIndex = (int)Session["index"];
// Восстанавливаем текущее состояние "Флажка"
CheckBox1.Checked = (bool)Session["Флажок"];
}
}
protected void lstSwitchThemes_SelectedIndexChanged(object sender, EventArgs e)
{
// Запоминаем новый выбор пользователя
Session["Theme"] = lstSwitchThemes.SelectedValue;
// Запоминаем новое состояние списка
Session["index"] = lstSwitchThemes.SelectedIndex;
// Сохраняем текущее состояние "Флажка"
Session["Флажок"] = CheckBox1.Checked;
// Первый вариант:
// Обновляем страницу с полным циклом,
// чтобы новая тема вступила в действие
//Response.Redirect(Request.Url.ToString());
// Второй вариант:
// Обновляем страницу без полного цикла,
// чтобы новая тема вступила в действие
Server.Transfer(Request.FilePath);
}
}
Сделаем некоторые пояснения по кодовой части страницы:
System, потому что:DirectoryInfo прописан
с Session, Server, Response, Request являются общедоступными свойствами класса System.Web.UI.Page,
который наследуется нашим классом TestSwitchThemes и явно
приобретает все эти свойстваSystem только потому, что в коде имеются
ключевые слова string, int, bool,
используемые при явном string, System. int,
System. bool.NET
Framework,
а не только специализированные Web-средстваТеперь осталось внести какое-либо видимое различие в оформления тем, чтобы мы могли убедиться, что программно была подключена действительно другая тема. Для экономии своих сил внесем минимальные изменения, например, сделаем разными цвета фона страницы.
Вызовите
на редактирование файл App_Themes/MyTheme1/ThemeCSS.css и
поменяйте в селекторе body определение
стиля фона background , чтобы фон страницы
стал зеленымbody
{
background:green;
font-family:Arial, Helvetica, sans-serif;
}
Вызовите
на редактирование файл App_Themes/MyTheme2/ThemeCSS.css и
поменяйте в селекторе body определение стиля
фона background , чтобы фон страницы стал краснымbody
{
background:red;
font-family:Arial, Helvetica, sans-serif;
}
Исполните
страницу и убедитесь в том, что пользователь может сам выбирать
варианты стилевого оформления страниц подключением соответствующих
темПодобным образом программно можно менять и другие стилевые
свойства страницы и ее элементов, например, именованные оформления элементов управления, определенные атрибутом SkinID. Не обязательно давать пользователю
возможность настройки стилевого оформления напрямую. Можно
сделать оформление страниц и элементов косвенно зависимым от
выбора пользователя.
Все, что было сказано для декларативного
способа подключения тем и приоритетов их применения, остается
справедливым и для
Очень часто требуется зафиксировать структуру страницы так, чтобы одни и те же элементы управления пользовательского интерфейса размещались в одном и том же месте как на одной странице, так и на множестве страниц сайта. Это позволяют сделать специальные страницы - шаблоны, которые существуют независимо, но подключаются к страницам по мере необходимости. Любая исполнимая страница может подключать только один из заранее заготовленных шаблонов.
Шаблон размечает
Перекомпоновка подключенного шаблона или его содержимого, а также подключение к исполнимой странице нового шаблона декларативно или программно приводит к немедленному изменению ее структуры и содержимого шаблонной части.
Исполнимая
страница получает от используемого шаблона его компоновку, содержимое и заполнитель. Заполнитель шаблона проецируется
на исполнимую страницу полностью. Если на исполнимой странице
есть хотя-бы одна группа, прикрепленная к соответствующей именованной
области шаблона, то

Замещающее содержимое на контекстной странице может располагаться
только в контейнерах, ссылающихся на зарезервированные мастер-страницей
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server"> </asp:Content>
Добавьте
к проекту командой Website/Add New Item шаблон с именем FirstMasterPage.master с
разделяемым кодом
Вот какой дескрипторный код создал мастер
<%@ Master Language="C#" AutoEventWireup="true"
CodeFile="FirstMasterPage.master.cs"
Inherits="FirstMasterPage" %>
<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>
Этот код почти такой-же, как и у заготовки обычной исполнимой страницы .aspx. Шаблоны представляют собой обычные страницы, за исключением нескольких отличий:
@Page используется директива @Master System.Web.UI.MasterPage ,
вместо базового класса System.Web.UI.Page для
обычной исполнимой страницыContentPlaceHolder используется
для резервирования именованных контекстных
областей только
в шаблонах. Если раскрыть вкладку Standard контекстно-зависимой
панели Toolbox при
редактировании обычной страницы, то мы этого элемента просто
не увидим, поскольку оболочка его скрывает до случая редактирования
шаблонаContentPlaceHolder ( держатель
места для содержимого ) шаблонной страницы можно размещать
в ячейках таблицы. При выполнении эти ячейки заполнятся присоединенным
содержимым, а остальные ячейки можно занять заполнителем,
который будет виден и доступен на любой странице, использующей
этот шаблон
Удалите
из кода ContentPlaceHolder и
через контекстное меню редактора выполните команду Add
Content Page (добавить
контекстную
страницу)
Оболочка сгенерирует такую заготовку файла Default.aspx
<%@ Page Language="C#" MasterPageFile="~/FirstMasterPage.master"
AutoEventWireup="true" CodeFile="Default.aspx.cs"
Inherits="_Default" Title="Untitled Page" %>
<%-- Add content controls here --%>
Получился пустой файл содержимого, где имеется только директива @Page
со стандартными атрибутами страницы и атрибутом подключения
шаблона.
<%--...--%> в
дескрипторный код файлов ASP.NETОболочка
прописала значение атрибута подключения MasterPageFile с
путем относительно корня Web-дерева сайта (там
наш шаблон и находится). Если уже подключенный к каким-то
страницам шаблон переместить из корня в другую папку Web-дерева,
то оболочка автоматически не меняет путь атрибута MasterPageFile во
всех ссылающихся на шаблон страницах, это придется делать
вручную. Поэтому нужно заранее
спланировать, будем ли мы использовать
Создайте
в панели Solution Explorer через контекстное
меню для корня Web-дерева проекта командой New Folder каталог MasterPages
Переместите
мышью в папку MasterPages шаблон FirstMasterPage.masterОткорректируем дескрипторный код контекстной страницы, для этого:
В панели Solution Explorer дайте файлу Default.aspx новое имя FirstMasterPage.aspx
Откорректируйте
дескрипторный код страницы FirstMasterPage.aspx,
указав новое местоположение шаблона, переименовав класс
поддержки страницы и назначив заголовок окна броузера<%@ Page Language="C#"
MasterPageFile="~/MasterPages/FirstMasterPage.master"
AutoEventWireup="true" CodeFile="FirstMasterPage.aspx.cs"
Inherits="FirstMasterPage" Title="Тестовая страница содержимого" %>
<%-- Add content controls here --%>
Откройте
файл FirstMasterPage.aspx.cs командой View
Code контекстного меню страницы и измените имя _Default класса страницы на FirstMasterPage
Назначьте
страницу FirstMasterPage.aspx стартовой
и исполните ее, чтобы убедиться в отсутствии ошибокПоявилась пустая страница с фоном, определенным темой по умолчанию MyTheme, включенной нами ранее в конфигурационный файл web.config
<configuration>
<system.web>
<pages theme="MyTheme" />
</system.web>
</configuration>
Никакого содержимого страница пока не имеет.
Добавьте
в файл FirstMasterPage.aspx произвольный
текст, например<%@ Page Language="C#"
MasterPageFile="~/MasterPages/FirstMasterPage.master"
AutoEventWireup="true" CodeFile="FirstMasterPage.aspx.cs"
Inherits="FirstMasterPage" Title="Тестовая страница содержимого" %>
<%-- Add content controls here --%>
<h1>Привет студентам из "страницы содержимого1"!</h1>
Если сейчас исполнить такую страницу, то мы получим ошибку времени выполнения, потому что содержимое страницы должно находиться в специальных именованных контейнерах
<asp:Content></asp:Content>
Поместите
строку текста в контейнер <asp:Content> и
исполните страницу<%@ Page Language="C#"
MasterPageFile="~/MasterPages/FirstMasterPage.master"
AutoEventWireup="true" CodeFile="FirstMasterPage.aspx.cs"
Inherits="FirstMasterPage" Title="Тестовая страница содержимого" %>
<%-- Add content controls here --%>
<asp:Content>
<h1>Привет студентам из "страницы содержимого1"!</h1>
</asp:Content>
Вновь произойдет ошибка выполнения, потому что каждый
контейнер <asp:Content></asp:Content> обязательно
должен ссылаться на свою
Откройте
на редактирование файл ~/MasterPages/FirstMasterPage.master в
режиме Design и поместите на шаблон из вкладки Standard элемент управления ContentPlaceHolder,
экземпляр которого мы ранее удалили
Перейдите
в режим Source на странице FirstMasterPage.master и
поместите внутрь созданного контейнера ContentPlaceHolder1 текстовую
строку, чтобы дескрипторный код стал таким<%@ Master Language="C#" AutoEventWireup="true"
CodeFile="FirstMasterPage.master.cs"
Inherits="FirstMasterPage" %>
<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">
<h1>Привет студентам из "именованной области1" мастер-страницы!</h1>
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Перейдите
в режим Design и убедитесь, что 
Теперь нужно настроить контекстную страницу, использующую шаблон.
Откройте
на редактирование в режиме Source контекстную
страницу FirstMasterPage.aspx,
к которой подключен шаблон, и определите в контейнере <asp:Content> идентификатор-ссылку ContentPlaceHolderID резервируемой
области шаблона, на которую будет ссылаться контекстный дескрипторПользуйтесь услугами подсказчика кода ,
который вызывается каждый раз при добавлении пробела внутри
дескриптора. Идентификатор ID самого контейнера <asp:Content> в
контекстной
странице определять необязательно, если только
мы не планируем управлять им программно. Измененный
код будет таким
<%@ Page Language="C#"
MasterPageFile="~/MasterPages/FirstMasterPage.master"
AutoEventWireup="true" CodeFile="FirstMasterPage.aspx.cs"
Inherits="FirstMasterPage" Title="Тестовая страница содержимого" %>
<%-- Add content controls here --%>
<asp:Content ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<h1>Привет студентам из "страницы содержимого1"!</h1>
</asp:Content>
Исполните
страницу FirstMasterPage.aspx, должен получиться
такой результат с учетом действия темы MyTheme,
подключенной в 
Поместите
на шаблон еще один резервирующий контейнер ContentPlaceHolder и
наполните его таким кодом<%@ Master Language="C#" AutoEventWireup="true"
CodeFile="FirstMasterPage.master.cs"
Inherits="FirstMasterPage" %>
<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">
<h1>Привет студентам из "именованной области1" мастер-страницы!</h1>
</asp:ContentPlaceHolder>
<br />
<asp:ContentPlaceHolder ID="ContentPlaceHolder2" runat="server">
<h1>Привет студентам из "именованной области2" мастер-страницы!</h1>
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Перейдите
на контекстную
страницу FirstMasterPage.aspx в
режиме Design, которая станет такой
Мы видим, что
Мы можем рассматривать итоговую страницу пользователя как
двухслойную. На нижнем слое находится
Иными словами,
Обратите внимание на заголовки именованных областей и их фон.
Там, где подставлено содержимое прикрепленного контейнера,
фон светлее и в скобках надпись ( Custom ) -
заказной. Там, где проявилось содержимое
Добавим непустой контейнер содержимого к нижней резервируемой
области
На
странице FirstMasterPage.aspx в режиме Design вызовите
контекстное меню для нижней зарезервированной области и выполните
команду Create Custom ContentОболочка добавит пустой контейнер содержимого и автоматически свяжет его в дескрипторном коде с именованной резервируемой областью.
Добавьте
в контейнер с содержимым какой-нибудь текст и несколько компонентов
из панели Toolbox и выполните страницуЭто очень удобная технология. Если планируется создание
нескольких страниц на базе
После того, как на вновь созданной странице с содержимым проявятся
На
нижней области контекстной
страницы FirstMasterPage.aspx вызовите
контекстное меню и выполните команду Default to Master's
Content, чтобы удалить содержимоеЕсли
Приведем более содержательный пример разработки страниц с
использованием шаблонов. Учитывая, что HTML поддерживает только
потоковую
В панели Solution Explore r вызовите контекстное меню
для папки MasterPages, которую мы
создали ранее,
и выполните команду Add New Item
В окне
мастера создания заготовок выберите шаблон Master
Page и создайте эталонную страницу с именем Title.master без
файла отделенного кода
Оболочка добавит заготовку эталонной страницы в каталог MasterPages, где ей и место.
Переведите
в редакторе эталонную страницу Title.master в
режим Design и удалите пока автоматически
созданный экземпляр элемента ContentPlaceHolder (просто
для тренировки)
В
режиме Design из вкладки Standard панели Toolbox поместите
в самом начале Image как
контейнер для размещения ID =" ImageBanner "Элемент Image из вкладки HTML здесь
не подойдет. Он не будет проявляться на контекстной
странице,
потому что не обрабатывается сервером по механизму runat="server" )
Вызовите
контекстное меню для папки MasterPages и
выполните команду Add Existing Item.
Найдите через открывшееся диалоговое окно файл Banner.png,
который находится в прилагаемом к данной работе каталоге Source,
и скопируйте его в папку MasterPages текущего
сайта
Выделите
экземпляр ImageBanner и присоедините
к нему через свойство ImageUrl рисунок Banner .png из
папки MasterPages Web-дерева сайта
Наш
Разместите
после <h1 style="color: Green">
Мы приветствуем Вас на нашем сайте!!!
</h1>
Элемент шаблона ContentPlaceHolder по умолчанию
растягивается по всей ширине страницы. Чтобы позиционировать
его на

В трех ячейках таблицы будет размещаться потенциально заменяемое
содержимое ContentPlaceHolder. В разных ячейках
таблицы мы сделали разный фон только для учебных целей, чтобы
сделать ячейки видимыми и показать, что фон ячеек таблицы с
Мы должны четко
представлять, что элементы управления ContentPlaceHolder и Content являются прозрачными контейнерами
для своего содержимого, если только мы искусстенно не создадим
в них фон другими элементами, например, элементом Panel, Image, Table. Поэтому, если мы на странице содержимого
не создадим свой фон в замещающих элементах Content,
то будет проявляться в итоговой странице фон элемента-контейнера
Поместите
на Table
Используя
боковые маркеры таблицы и команды меню Layout оболочки, постройте
таблицу из трех строк и двух столбцов, чтобы она соответстворвала
приведенному выше рисункуВ конечном виде таблица вместе с вутренними стилями должна описываться следующими HTML -кодом
<table>
<tr>
<td colspan="2">
</td>
</tr>
<tr>
<td style="width: 25%; background-color: #9DFF7E" valign="top">
</td>
<td style="background-color: #FFB8FF">
</td>
</tr>
<tr style="background-color: #FFFF92">
<td colspan="2">
</td>
</tr>
</table>
Внешний вид таблицы будет таким

Теперь все готово для размещения элементов управления
в ячейках
Поместите
из вкладки Standard панели Toolbox в
верхнюю строку таблицы компонент Panel,
к которому мы должны присоединить рисунок, задающий
фон ячейки
Задайте
для созданного экземпляра элемента управления Panel значения свойств: Width=100% ; Height=100%, чтобы элемент полностью занял верхнюю ячейку
таблицы
Через
проводник Windows найдите в
прилагаемом к данной работе каталоге Source файл BackTitleSrc.jpg и в любом графическом
редакторе вырежьте из него область с хорошо стыкуемыми
при повторении рисунка границами, или возьмите
мною вырезанный готовый рисунок BackTitle.jpgРисунок не должен быть слишком большим, чтобы "не застревал в проводах и не тормозил " по пути к пользователю.
В
панели Solution Explorer в
контекстном меню для папки MasterPages выполните
команду Add Existing Item,
найдите рисунок BackTitle.jpg и
скопируйте его в эту папку
Выделите
на странице экземпляр Panel1 в
верхней строке таблицы и через панель инструментов Properties присоедините
в свойстве BackImageUrl
рисунок BackTitle.jpg, который многократным повторением займет
всю Теперь можно разместить в ячейках таблицы прозрачные
контейнеры-шаблоны элемента управления ContentPlaceHolder.
Поместите
из вкладки Standard панели Toolbox в
верхнюю строку таблицы в объект Panel1 элемент-контейнер ContentPlaceHolder, который
будет представлять на странице именованную
область ContentPlaceHolder1 для
размещения
То
же самое сделайте для правой-средней и нижней
ячеек таблицы
В
контейнер ContentPlaceHolder1 вставьте
и отредактируйте такую строку<div style="font-weight: bold; font-size: xx-large; color: red; text-align: center">
Сведения об автошколе в целом
</div>
Вставьте
в правый-средний контейнер ContentPlaceHolder2 любой
текст, например, такой или его частьВот уже более 15 лет мы занимаемся подготовкой водителей
категории "B" в г.Красноярске и всегда занимали первые места
в сводках МРЭО ГИБДД по качеству обучения. Автошкола всегда нацелена
на успех наших клиентов в сдаче экзаменов ГАИ с первого раза
и своевременном получении водительского удостоверения.
Мы обеспечиваем максимальные удобства своим клиентам. Для
этого существуют вечерняя и воскресная формы обучения.
Наши курсанты имеют возможность бесплатно и неограниченно пользоваться
компьютерным классом. Учебные автомобили прибывают по заявке
клиента к назначенному им месту. Развивается сеть филиалов автошколы
в г.Красноярске.
Наша компьютерная экзаменационная программа успешно используется
в ГИБДД г.Красноярска, Железногорска, Назарово, Емельяново, Шарыпово
для государственной аттестации кандидатов в водители. Мы неоднократно
выпускали цветные учебно-методические пособия по Правилам дорожного
движения, которыми постоянно пользуются большинство автошкол
города и края.
Лекционные занятия в автошколе ведут квалифицированные преподаватели
с учеными степенями и званиями с применением современных компьютерных
технологий. Комплексный подход к обучению и разнообразие форм
позволяют максимально сократить усилия наших клиентов и сроки
усвоения ими учебного материала. Парк учебных автомобилей насчитывает
более 30 штук, включая иномарки.
В
нижний контейнер ContentPlaceHolder3,
резервирующий место под <strong> Автошкола Диалог-Сервис в целом работает без перерыва на обед и выходных с 8 часов утра до 9 часов вечера!!! </strong>
Поместите
в левую ячейку таблицы надпись, а из вкладки Standard панели Toolbox три гиперссылки
элемента управления HyperLink Дескрипторный код содержимого левой ячейки таблицы,
которое размещается внутри тегов <td></td>,
будет примерно таким
<strong style="color: Blue">Наши филиалы:</strong><br /> <br /> <asp:hyperlink id="HyperLink1" runat="server">Ленинский район</asp:hyperlink><br /> <br /> <asp:hyperlink id="HyperLink2" runat="server">Центральный район</asp:hyperlink><br /> <br /> <asp:hyperlink id="HyperLink3" runat="server">Свердловский район</asp:hyperlink><br /> <br /> <asp:hyperlink id="HyperLink4" runat="server">Октябрьский район</asp:hyperlink>
Сейчас мы пока не определяем в гиперссылках элементы
адресации до тех пор, пока не создадим несколько
контекстных
страниц, использующих эту
Итак, таблицу мы заполнили. Попробуем разместить
еще что-нибудь ниже таблицы, например, товарный
знак и страшилку от воров
Отступите
ниже таблицы одну-две строчки и добавьте из вкладки HTML панели Toolbox элемент
управления Image.
Щелкните на нем правой кнопкой мыши и выполните
команду Run As Server Control,
чтобы содержимое элемента проявилось на будущей
контекстной
странице как заполнитель
В
панели Solution Explorer вызовите
контекстное меню для папки MasterPages и
скопируйте в проект командой Add Existing
Item из
прилагаемого каталога Source рисунок LIGHT.ICO нашего
Через
панель Properties и свойство Src ( Source - источник) присоедините ссылку на файл LIGHT .ICO к
нашему компоненту отображения Image
Правее
Окончательный дескрипторный код этого раздела будет таким
<p style="text-align: right; color: Blue; font-family: 'Courier New'; font: bold italic">
<img id="IMG1" runat="server" src="LIGHT.ICO" />
nbsp;Copyright copy 2009
</p>
Для
наглядности, поместите еще один контейнер в самом
низу <asp:ContentPlaceHolder ID="ContentPlaceHolder4" runat="server">
<strong><em>Вы уж, пожалуйста, наведывайтесь к нам почаще!</em></strong>
</asp:ContentPlaceHolder>
И последний штрих к оформлению
Найдите
вверху дескрипторного кода самый внешний дескриптор <div> и определите в нем
внутренний стиль CSS такой<body>
<form id="form1" runat="server">
<div style="text-align: center">
..................................
</div>
</form>
</body>
Наступил момент истины! Пора тиражировать контекстные
страницы на базе созданной
В продолжение упражнения создадим 5 контекстных страниц с простыми именами:
Есть несколько способов создания с помощью
оболочки контекстных страниц
на базе готовой
В
панели Solution Explorer выделите корень Web-дерева и выполните команду меню Website/Add
New Item (или команду Add New Item контекстного меню)
В
появившемся диалоговом окне задайте имя страницы Satellite.aspx и отметьте показанные настройки,
включая Select
master page
Оболочка
предложит еще одно окно, в котором выберите

Созданная страница Satellite.aspx с
отделенным кодом будет добавлена в корень Web-дерева
и будет содержать контейнеры с подключенным пустым
содержимым для всех шаблонов выбранной
<%@ Page Language="C#" MasterPageFile="~/MasterPages/Title.master"
Title="Untitled Page" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder2" Runat="Server">
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder3" Runat="Server">
</asp:Content>
<asp:Content ID="Content4" ContentPlaceHolderID="ContentPlaceHolder4" Runat="Server">
</asp:Content>
В
панели Solution Explorer выделите
нужную Будет создана контекстная
страница с дежурным
именем, размещенная в том же каталоге, что и выделенная
MasterPageFile будет
прописан относительно корня Web-дерева как абсолютный
адрес в пределах сайта
MasterPageFile="~/
Это значит, что можно переместить
контекстную
страницу в любую
папку в пределах Web-дерева, и везде адрес
Поэтому необходимо
соблюдать простое правило, при котором не
придется долго искать ошибки:
перемещать
Переименуйте
созданную контекстную страницу Default.aspx на Satellite1.aspx и
переместите ее в
Откройте
Появится контекстное меню с уже известной нам командой Add Content Page, выполнение которой создаст файл Default.aspx.
Переименуйте
созданную контекстную страницу Default.aspx на Satellite2.aspx и
переместите ее в
Получите
в Теперь необходимо скорректировать заготовки контекстных
страниц
Выполните
команду Window/Close All Documents,
чтобы закрыть все редактируемые
на текущий момент файлы
В
панели Solution Explorer щелкните
правой кнопкой мыши на файле ~/MasterPages/Title.master и
выполните команду View Designer, чтобы открыть
Поочередно
выделяя элементы гиперссылок, установите их свойство NavigateUrl на соответствующие
контекстные
страницы Satellite1.aspx, Satellite2.aspx, Satellite3.aspx, Satellite4.aspx.
Сохраните и закройте Отредактируем страницы содержимого, начнем с Satellite.aspx.
В
панели Solution Explorer назначьте
страницу Satellite.aspx стартовой
и откройте ее на редактирование в режиме Design Что мы видим на данном этапе времени проектирования:
Удалите
в режиме Design командой контекстного
меню Default
to Master 's Content все контейнеры контекста <asp:Content></asp:Content>
из
страницы Satellite.aspxЭта страница у нас будет стартовой без своего
содержимого и будет отображать только содержимое
Убедитесь,
что после удаления закрепленных блоков контекстной
страницы проявился нижний слой - содержимое шаблонов
Исполните
страницу Satellite.aspx, получится
ожидаемый результат
Пощелкайте
по ссылкам и обратите внимание, как меняется
адрес в броузере (ссылки работают). На адресуемых
страницах мы пока не убрали и не изменили контейнеры
содержимого, поэтому там на месте контейнеров
шаблона ничего не будет (пустое содержимое контейнеров
место при исполнении не занимает).Теперь нужно наполнить контекстные страницы, которые мы подгружаем по ссылкам, индивидуальным содержимым.
Приведем окончательный вариант дескрипторного кода для всех страниц данного примера:
Обратите внимание, что все контейнеры ContentPlaceHolder должны находиться внутри
дескриптора <form></form>.
<%@ Master Language="C#" %>
<script runat="server">
</script>
<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">
nbsp;<asp:Image ID="ImageBanner" runat="server" ImageUrl="~/MasterPages/Banner.png" /><br />
nbsp;<h1 style="color: green">
Мы приветствуем Вас на нашем сайте!!!
</h1>
<table>
<tr>
<td colspan="2">
<asp:Panel ID="Panel1" runat="server" BackImageUrl="~/MasterPages/BackTitle.jpg"
Height="100%">
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
nbsp;<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">
<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><br />
<br />
<asp:HyperLink ID="HyperLink4" runat="server" NavigateUrl="~/Satellite4.aspx">Октябрьский район
</asp:HyperLink>
</td>
<td style="background-color: #FFB8FF">
<asp:ContentPlaceHolder ID="ContentPlaceHolder2" runat="server">
<p>Вот уже более 15 лет мы занимаемся подготовкой водителей
категории "B" в г.Красноярске и всегда занимали первые места
в сводках МРЭО ГИБДД по качеству обучения. Автошкола всегда нацелена
на успех наших клиентов в сдаче экзаменов ГАИ с первого раза
и своевременном получении водительского удостоверения.</p>
<p>Мы обеспечиваем максимальные удобства своим клиентам. Для
этого существуют вечерняя и воскресная формы обучения.
Наши курсанты имеют возможность бесплатно и неограниченно пользоваться
компьютерным классом. Учебные автомобили прибывают по заявке
клиента к назначенному им месту. Развивается сеть филиалов автошколы
в г.Красноярске.</p>
<p> Наша компьютерная экзаменационная программа успешно используется
в ГИБДД г.Красноярска, Железногорска, Назарово, Емельяново, Шарыпово
для государственной аттестации кандидатов в водители. Мы неоднократно
выпускали цветные учебно-методические пособия по Правилам дорожного
движения, которыми постоянно пользуются большинство автошкол
города и края. </p>
<p> Лекционные занятия в автошколе ведут квалифицированные преподаватели
с учеными степенями и званиями с применением современных компьютерных
технологий. Комплексный подход к обучению и разнообразие форм
позволяют максимально сократить усилия наших клиентов и сроки
усвоения ими учебного материала. Парк учебных автомобилей насчитывает
более 30 штук, включая иномарки.</p>
</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 copy 2009
</p>
<asp:ContentPlaceHolder ID="ContentPlaceHolder4" runat="server">
<strong><em>Вы уж, пожалуйста, наведывайтесь к нам почаще!</em></strong>
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Все контейнеры <asp:Content> уничтожены,
поэтому страница используется только как запускающая
и не добавляет к
<%@ Page Language="C#" MasterPageFile="~/MasterPages/Title.master"
Title="Untitled Page" %>
Страница имеет все контейнеры переопределяющего
содержимого, поэтому от
<%@ 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>
Страница имеет все контейнеры переопределяющего
содержимого, поэтому от
<%@ 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>
Третий контейнер страницы содержимого отсутствует,
поэтому на его месте проявится содержимое третьего
шаблона
<%@ 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>
Второй контейнер страницы отсутствует,
поэтому на его месте проявится содержимое второго
шаблона
<%@ Page Language="C#" MasterPageFile="~/MasterPages/Title.master" Title="Untitled Page" %>
<asp:Content runat="Server" ContentPlaceHolderID="ContentPlaceHolder1">
<div style="font-weight: bold; font-size: xx-large; color: red; text-align: center">
Сведения о филиале в Октябрьском районе
</div>
</asp:Content>
<asp:Content runat="Server" ContentPlaceHolderID="ContentPlaceHolder3">
</asp:Content>
<asp:Content runat="Server" ContentPlaceHolderID="ContentPlaceHolder4">
</asp:Content>
Прежде, чем приступить к программному управлению
элементов
Такой порядок означает, что если мы программно
меняем одни и те же настройки в
В контекстной странице мы можем менять
только содержимое контейнеров <asp:Content>,
а содержимое заполнителей
Вначале рассмотрим вопросы программирования заголовка
<head> в HTML-выводе. <head>...</head> обычной
страницы, где можно задавать все составляющие его
дескрипторы и это появится на результирующей странице.
Но иногда на контекстной странице нужно определить
свои дескрипторы заголовка. Декларативно (на
этапе проектирования) в контекстной странице
можно переопределить только дескриптор <title>,
добавив в
директиву @Page атрибут Title="..." контекстной
страницы. В этом случае дескриптор <head>
Программно можно переопределять не только дескриптор <title>,
но и другие дескрипторы заголовка <head> <head> Page Page. объекта
текущей контекстной страницы, у которого, в свою
очередь, свойство и
определяет ссылку на объект Page
Ниже
приведены равноценные коды получения ссылки на
объект Page
Page masterPage = base.Master.Page;
Page masterPage = this.Master.Page;
Page masterPage = Master.Page;
Ключевые слова base или this не
являются обязательными. Они напоминают, что является
свойством объекта текущей страницы.
Создайте
копию страницы 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" %>
Исполните
страницу с новым заголовком окна броузера - результат
будет таким
Поскольку мы не создавали для страницы 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() срабатывает позднее.
Рассмотрим управление элементами заполнителя <h1>,
определенного в заполнителе так
<h1 style="color: Green">
Мы приветствуем Вас на нашем сайте!!!
</h1>
Его отображение в броузере будет следующим

Дополните
дескриптор <h1> Title.master необходимыми
для программного управления атрибутами<h1 style="color: Green" runat="server" id="Header1">
Мы приветствуем Вас на нашем сайте!!!
</h1>
Управлять будем из страницы SatelliteExt.aspx одним из двух способов:
<h1> в
отдельное свойство с именем MyHeader1 и
из контекстной страницы будем обращаться к
нему через это свойство<h1> по
его ID и будем
обращаться к нему напрямую
Двойным
щелчком на
свободном от элементов управления месте <%@ 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>
Дополните
контекстную страницу 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>
Исполните
контекстную страницу 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>
Метод FindControl() ищет указанный
элемент на
Исполните
страницу SatelliteExt.aspx и
убедитесь, что дескриптор <h1>,
относящийся к заполнителю 
Второй способ более предпочтительный, поскольку
мы не вмешиваемся в код спроектированной
Иногда может возникнуть необходимость дать возможность
пользователю подключать необходимые Page. в
директиве @Page. Теперь нам нужно программно
менять атрибут Page.MasterPageFile в
коде контекстной страницы.
Здесь нужно иметь ввиду следующее:
ContentPlaceHolderIDPage.PreInit контекстной
страницы.
Если это сделать в обработчиках более поздних
событий, то будет сгенерировано исключениеУчитывая, что наши страницы Satellite.aspx, Satellite1.aspx, Satellite2.aspx, Satellite3.aspx согласованы
с Title.master, сделаем их копии
и настроим под динамическую смену
В
панели Solution Explorer создайте копию файла Title.master с
именем Title1.master
Откройте
<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 стартовой
Откройте
<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] |
~/ |
|
Items[1] |
~/ |
Установите
для списка 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>
Откройте
поочередно файлы 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>
Исполните
начальную страницу SatelliteDynamic.aspx и
убедитесь, что мы дали пользователю полнофункциональный
механизм выбора шаблонов форматированияПринципиально возможно подключение одной
Но мы, все-таки, рассмотрим эту
возможность на примере Level1 к верхнему Level0.
Создайте в корне Web-дерева 
Код
страницы сделайте таким<%@ 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>
Теперь
также в корне 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>
Обратите внимание, что при попытке переключить
созданную

Это значит, что автоматизированный графический
режим Design
работает только для
Выполните
для страницы 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>
Назначьте
контекстную страницу TestMasterPageLevel.aspx стартовой
и исполните ееРезультат будет таким

Итак, все работает, но нам это не надо - слишком запутано и посмотреть в Design нельзя!
Для страниц, которые не имеют подключения
<configuration>
<system.web>
<pages masterPageFile="XXX.master" />
</system.web>
</configuration>
Этот подход не считается надежным, поскольку
требует строгого согласования всех контекстных
страниц с шаблонами одной

Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.