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

Определенный в
Пусть отдельный заголовочный
<h1 style="color:red; text-align:center">Этот заголовочный текст будет центрирован в текущем документе и иметь красный цвет (бледный вид)!</h1>
Отклик
Определение внутренних стилей отдельных < в своем дескрипторном блоке <. Синтаксис встроенных стилей следующий

Атрибут type="text/ body и h1 совпадают с именами
Имена классов ".имя_класса" выбираются произвольно. В том class="имя_класса". Классы для конкретного вида тегов "тег.имя_класса" используются только в тегах заданного типа по той же самой схеме class="имя_класса".
Пусть страница имеет код, приведенный ниже (файл embedded.htm в каталоге CSS рассматриваемой темы)
<html>
<head>
<title>Документ со встроенной CSS</title>
<meta content="text/html; charset=windows-1251" http-equiv="Content-Type">
<style type="text/css">
body
{
background:white url(MyWeb.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>
</head>
<body>
<h1>
Заполните анкету!</h1>
<form>
<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-документу выполняется добавлением в блок < <link> или @import.
Пусть имеется два файла с внешними стилями и произвольными именами, например, и default.. Вот варианты их подключения в HTML-документ MyPage. ( обязательно в заголовочный блок < ):
| Вариант | В блоке < |
Замечания |
|---|---|---|
| Подключается одна |
<link rel="stylesheet" href="header.css"> |
|
| Подключается две |
<link rel="stylesheet" href="header.css"> <link rel="stylesheet" href="default.css"> |
|
| Подключается одна |
<style type="text/css">
@import url(header.css);
</style>
|
Не поддерживается |
| Подключается две |
<style type="text/css">
@import url(header.css);
@import url(default.css);
</style>
|
Не поддерживается |
| Подключается две |
<style type="text/css">
@import url(header.css);
</style>
|
В самом начале файла header.css имеется голая строка прямого подключения:@import url(default.css) |
| Подключается две |
<style type="text/css">
@import url(header.css);
</style>
<link rel="stylesheet" href="default.css">
|
Порядок следования не влияет |
| Подключается две |
<link rel="stylesheet" href="default.css">
<style type="text/css">
@import url(header.css);
</style>
|
Порядок следования не влияет |
| Подключается три |
<link rel="stylesheet" href="default.css">
<style type="text/css">
@import url(header.css);
body
{
background:white url(MyWeb.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>
|
Подключается две внешних таблицы в дополнение к встроенной. Встроенные стили теоретически должны иметь выше приоритет, чем внешние. Но это зависит от конкретного Порядок следования не влияет |
| Подключается три |
<style type="text/css">
body
{
background:white url(MyWeb.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 rel="stylesheet" href="default.css">
|
Подключается две внешних таблицы в дополнение к встроенной. Встроенные стили теоретически должны иметь выше приоритет, чем внешние. Но это зависит от конкретного Порядок следования не влияет |
Чтобы проверить сказанное, выполните следующее (вручную, без Visual Studio 2005!)
Найдите в прилагаемом каталоге CSS файл embedded.htm и в этом же каталоге сделайте из него две копии с именами TestCSS.htm и ExternalCSS.css
Откройте в <head > встроенный стиль на строку подключения внешней CSS<link rel="stylesheet" href="ExternalCSS.css">
Откройте в
Откройте страницу
Опробуйте другие варианты подключения внешней CSS, приведенные ранее (если хотите!)Итак, внешняя CSS, это обычный текстовый файл, которому традиционно назначают расширение .css для лучшей узнаваемости, хотя может использоваться любое расширение. Мы убедились, что его можно создавать отдельно в любом
Создайте через Проводник Windows новый каталог с именем WebSite6
Откройте этот каталог через оболочку Visual Studio 2005 командой File/Open/Web Site
Выполните команду Website/Add New Item, выберите вариант Style Sheet и оставьте имя файла по умолчанию StyleSheet.css Оболочка добавит в проект новый файл
Наша главная задача, как программистов, - понимать и правильно
Не будем использовать созданную оболочкой заготовку StyleSheet.css, а научимся подключать свою
Откройте созданный нами ранее почти пустой проект WebSite6 (если не открыт)
Выполните команду Website/Add Existing Item. В появившемся диалоговом окне войдите в каталог CSS (мы в нем уже работали) и отметьте нужные файлы, удерживая при этом клавишу Ctrl
После щелчка на кнопке Add оболочка физически скопирует выделенные файлы в файл проекта WebSite6 и они появятся в панели Solution Explorer. Если вы не увидели там этих файлов, то щелкните на кнопке Refresh панели Solution Explorer, чтобы оболочка обновила представляемую после копирования информацию

Назначьте статическую страницу TestCSS.htm стартовой (команда Set As Start Page )и запустите ее на выполнение, чтобы убедиться, что и в оболочке она работает точно также, как и ранее в автономном режимеЕсли страница не содержит исполняемого ASP.NET -кода, то система ASP.NET ничего с ней не делает, а отсылает в неизменном виде клиенту. Если посмотреть на исходный
<html>
<head>
<title>Документ со встроенной CSS</title>
<meta content="text/html; charset=windows-1251" http-equiv="Content-Type">
<link rel="stylesheet" href="ExternalCSS.css">
</head>
<body>
<h1>
Заполните анкету!</h1>
<form>
<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>. Чтобы избавиться и от этого замечания редактора, нужно добавить атрибут
<form action=TestCSS.htm>
Посмотрите, как и в этом случае нам услужливо помогает подсказчик кода IntelliSense, предлагающий выбрать из списка файлов целевую страницу на сервере, которая будет принимать данные от формы

Вообще-то, большинство броузеров при пропущенном атрибуте полагают, что целевой будет та же самая страница. Но чтобы успокоить HTML редактор окончательно, укажем эту страницу явно.
Вызовите контекстное меню щелчком правой кнопки мыши на свободном месте верхней части каркаса оболочки и сбросьте флажок HTML Source Editing, чтобы закрыть одноименную панель настройки редактора
Удалите из заголовочного блока страницы код подключения внешней <link rel="stylesheet" href="ExternalCSS.css">
Переведите страницу в режим Design и посмотрите, какая она сразу стала блеклая (тусклая, бледная, невзрачная, некрасивая, ... - студент Леша Зиборов, продолжай! Только ты можешь дочитать до этого места!)
Вернитесь в режим Source и убедитесь, что оболочка добавила нужный
Опять удалите
Перейдите в режим Design, откройте панель Properties и через раскрывающийся список в ее верхней части выберите объект DOCUMENT
Найдите свойство
Очистите поле свойства StyleSheet, оболочка вновь удалит Таблицы CSS применяются не только к простым .
Откройте панель ToolboxМы видим, что доступной является только вкладка HTML, потому, что наша тестовая страница TestCSS.htm имеет расширение .htm.
Переименуйте в панели Solution Explorer тестовую страницу в TestCSS.aspx и сделайте ее же принимающей, исправив <form><form action=TestCSS.aspx runat="server">
Поместите на страницу из вкладки Standard текстовую метку Label и в панели Properties определитеCssClass=label Text=Стиль класса label
Откройте через Solution Explorer файл ExternalCSS.css и добавьте стилевое правило для класса label (рис ) Добавление нового стиля в класс label файла ExternalCSS.cssbody
{
background:white url(MyWeb.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;
}
.label
{
background-color:Green;
color:White;
font:bold;
font-size:x-large;
font-family:Courier New;
}
Выполните страницу, которая в 
Краткое знакомство с CSS и их поддержкой в Visual Studio 2005 закончили!
Применение CSS для стилевого оформления страниц ASP.NET имеет некоторые ограничения. Дело в том, что CSS являются решением стороны
Как и CSS, темы определяют набор стилей, которые называют оформлениями и которые можно применять на многих страницах ASP.NET. Особенности тем состоят в следующем:
Все темы помещаются в каталог с зарезервированным именем App_Themes, который можно добавить к приложению в панели Solution Explorer, выполнив команду Add ASP.NET Folder/Theme контекстного меню для узла приложения

Каждая тема должна храниться в своей одноименной папке и может состоять из нескольких файлов

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

Для темы можно все стилевые настройки элементов управления разместить в одном файле оформлений, а можно и в нескольких. Иногда просто удобнее группировать оформления по отдельным категориям элементов управления в соответствующих файлах. Для ASP.NET это не имеет никакого значения, поскольку она все равно считывает все файлы оформлений в каталоге темы как неделимое целое определения одной темы.
Проверим сказанное на практике:
Добавьте к проекту новую страницу TestTheme.aspx с раздельным кодом
Добавьте на страницу из вкладки Standard следующие элементы управленияBulletedListLabel CheckBox Button
Назначьте свойства
В панели Solution Explorer сделайте копию файла TestTheme.aspx и присвойте копии имя FirstSkin.aspx. Из него мы в дальнейшем сделаем файл оформлений
Удалите файл поддержки FirstSkin.aspx.cs
Настройте декларативно в панели Properties стилевые свойства объектов страницы FirstSkin.aspxBulletedList1:BackColor="Yellow"BorderColor="Red"BorderStyle ="Ridge "BorderWidth ="10px"BulletStyle="Numbered"ForeColor="Blue "Label1:BackColor="Blue "ForeColor="Yellow"ToolTip ="Текстовая метка"CheckBox1:BackColor="Red"BorderStyle ="Groove "Font -Bold ="True"ForeColor="White"Button :BackColor="#FFC0C0"BorderColor="Blue "BorderStyle ="Solid "BorderWidth ="2px"Font -Bold ="True"ForeColor="Blue "Внешний вид элементов управления после проведенных стилевых настроек должен быть таким

Перейдите в режим Source и удалите из файла FirstSkin.aspx весь код, кроме открывающих (рис ) Оставшийся код в файле 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
Создайте в приложении папку с зарезервированным именем
В панели Solution Explorer Тема подключается к странице с помощью атрибута @Page. Так, например, при применении темы с именем каталога MyTheme к нашей тестовой странице TestTheme.aspx
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="TestTheme.aspx.cs" Inherits="TestTheme"
Theme="MyTheme" %>
Тему можно подключить к странице и в панели Properties через свойство объекта DOCUMENT. В этом случае оболочка автоматически добавит атрибут к @Page с выбранным значением.
В раскрывающемся списке панели Properties для страницы TestTheme.aspx выделите объект DOCUMENT и установите свойство Theme ="MyTheme"
Назначьте страницу TestTheme.aspx стартовой и выполните ееДолжен получиться такой результат

Естественно, что переопределяются только те стилевые настройки элементов управления страницы, которые указаны в подключенной теме. Остальные настройки не переопределяются.
Вспомните, что в при подключении CSS стили начинают действовать на отображение элементов немедленно, на действие стилей мы увидим только на этапе выполнения. Механизм тем реализует стилевые настройки элементов управления, подключенные к форматируемой странице извне.
Но элементы управления страницы могут иметь свои индивидуальные стилевые настройки, которые мы им декларативно назначим при разработке страницы. В этом случае приоритет будут иметь одноименные настройки, указанные в подключаемой теме. Проверим это...
Измените в странице TestTheme.aspx атрибуты BackColor="Black " и ForeColor="Yellow" элемента CheckBox1, чтобы он имел черный фон и желтый текст
Выполните страницу и убедитесь, что элемент CheckBox1 будет иметь цвет фона красный, а Theme ="MyTheme"Объект DOCUMENT страницы имеет еще одно свойство StyleSheetTheme, к которому также можно подключить внешнюю тему. В этом случае приоритет будут иметь индивидуальные настройки элементов управления, которые в них были явно определены. Но те настройки по умолчанию, которые мы не определяли на странице, но которые содержатся в теме, действуют на свойства по умолчанию.

Любой вариант влияния темы на элемент управления можно отключить, если установить в этом элементе свойство EnableTheming="False".
Для страницы TestTheme.aspx в панели Properties выделите объект DOCUMENT, очистите поле его свойства StyleSheetTheme и подключите тему MyTheme к свойству Theme
Выделите объект CheckBox1 с индивидуальными настройками BackColor="Black "; ForeColor="Yellow" и установите для него EnableTheming="False"
Выполните тестовую страницу и убедитесь, что красивые настройки темы для этого элемента не действуют, а остались только настройки по умолчанию и индивидуальная настройка ![]() |
![]() |
Выделите объект CheckBox1 и верните для него EnableTheming="True"Стилевые настройки, которые мы до сих пор определяли в файле оформлений темы, являются настройками по умолчанию и применяются для всех элементов управления
Если просто определить в теме несколько вариантов настроек для одного и того же элемента управления, то ASP.NET выдаст ошибку об обнаружении неоднозначности. В этом случае в теме нужно применять именованные оформления с помощью атрибута SkinID. Тогда в странице наряду с общим подключением темы с помощью свойства можно будет определить значения SkinID именованных настроек элементов управления.
Значения SkinID в определениях темы должно быть уникальным только в группе однотипных элементов. Это значит, что мы можем создать несколько групп настроек разнотипных элементов с одинаковыми значениями атрибута SkinID и подключать из одной темы, по мере необходимости, к каждому элементу управления свои индивидуальные настройки.
Добавьте в страницу TestTheme.aspx элемент Table из вкладки HTML панели Toolbox. Таблицу расположите между кнопкой и Для нашего примера таблица должна иметь три столбца и пять строк. Оболочка не обладает развитыми средствами редактирования таблиц, поэтому проще настроить таблицу в режиме Source.
Поместите из вкладки Standard панели Toolbox в средний столбец таблицы пять серверных элементов Label , а в правый - пять серверных элементов CheckBox
Установите в добавленных объектах свойства в соответствии с контекстом таблицыSkinID не подключен: действуют общие настройки по умолчанию |
Label2 |
CheckBox2 |
Именованные настройки подключены: SkinID="Variant3" |
Label3 |
CheckBox3 |
Именованные настройки подключены: SkinID="Variant4" |
Label4 |
CheckBox4 |
SkinID="Variant5" подключен, но тема подавлена: EnableTheming="False" |
Label5 |
CheckBox5 |
Подключен несуществующий SkinID="XXX": настройки темы не действуют |
Label6 |
CheckBox6 |
Откройте файл оформлений FirstSkin.skin и дополните его индивидуальными настройками стилей, чтобы общий код его стал таким(рис ) Код файла оформлений FirstSkin.skin темы MyTheme<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" />
<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, то эти стилевые настройки никогда не будут применяться.
Сложные элементы управления включают в себя несколько разделов, требующих индивидуальных стилевых оформлений. Эти настройки могут занимать много места, если их использовать вместе с дескрипторным кодом страницы. Поэтому для таких элементов выносить громоздкий код стилевых настроек в отдельный файл оформлений очень даже удобно. Приведем пример с настройками элемента .
Создайте новую страницу со встроенным кодом поддержки и с именем TestCalendar.aspx
Назначьте страницу стартовой и поместите на нее из вкладки Standard элемент управления Calendar
Определите для объекта Calendar1 следующие стилевые настройки(рис ) Стилевые настройки объекта Calendar1 страницы TestCalendar.aspx<asp:Calendar ID="Calendar1" runat="server"
BackColor="white" ForeColor="black" BorderColor="black"
BorderStyle="solid" CellSpacing="1" Font-Names="Verdana"
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
Скопируйте из страницы TestCalendar.aspx в файл оформлений Calendar.skin весь дескрипторный код объекта Calendar1 вместе с его стилевыми настройками и удалите в копии атрибут ID="Calendar1"
Удалите в дескрипторном коде страницы TestCalendar.aspx код стилевых настроек объекта Calendar1, выделенный в приведенной выше таблице красным цветом, чтобы от объекта осталось только простое "мокрое место"<asp:Calendar ID="Calendar1" runat="server"> </asp:Calendar>
Через панель Properties выделите объект DOCUMENT и поключите к странице тему MyTheme в свойстве Theme
Выполните страницу и убедитесь, что вынесенный со страницы в тему большой блок стилевых настроек элемента Calendar работает также, как если бы он находился на самой страницеНиже приведены два варианта представления объекта Calendar1
![]() |
![]() |
С помощью с разными рисунками в зависимости от контекста применения. Пусть для кнопок OK будет использован один рисунок, а для кнопок Cancel - другой. Темы позволяют легко решить эту задачу.
В панели Solution Explorer через контекстное меню на папке MyTheme командой New Folder создайте подпапку ButtonImages для хранения рисунков кнопок
В панели Solution Explorer через контекстное меню на новой папке
Добавьте на страницу TestCalendar.aspx две картиночных кнопки ImageButton из вкладки Standard панели Toolbox и настройте через одноименные свойства в панели 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, чтобы добавить в тему новый файл оформления
Скопируйте настроенные ImageButton в файл Buttons.skin, предварительно очистив его от автоматически сгенерированных инструкций
Откорректируйте оформления в файле Buttons.skin, чтобы они выглядели так<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 в файле TestCalendar.aspx, чтобы от них осталось следующее<asp:ImageButton ID="ImageButton1" runat="server" SkinID="OKButton" /> <asp:ImageButton ID="ImageButton2" runat="server" SkinID="CancelButton" />
Исполните страницу Посмотрите, на странице находится дескрипторный код только создания сложных элементов управления, а большой код тонких настроек вынесен в файлы темы. Это очень удобно и для централизованного изменения стилевого оформления элементов управления, и для читабельности самой страницы.
Если у нас имеются хорошие наработки CSS, то ASP.NET позволяет использовать их для форматирования HTML-
Theme объекта DOCUMENT страницыCssClass элементов управления страницы<link>, используемого при традиционном способе подключения к странице, проследить, чтобы заголовочный <head runat="server"> ). В этом случае ASP.NET сама сгенерирует столько <link> в выходном Проверим это на примере. В панели Solution Explorer оболочки выполните следующие действия:
Скопируйте файл TestCSS.aspx и назначьте копии имя ThemeCSS.aspx и назначьте новую страницу стартовой
Скопируйте ThemeCSS.css
Переместите файл ThemeCSS.css в папку MyTheme проекта
Удерживая клавишу Ctrl, выделите файлы BackgroundImage.bmp и MyWeb.jpg в корне виртуального каталога и выполните для них команду Copy контекстного меню
Щелкните правой кнопкой мыши на узле MyTheme и выполните команду Paste, чтобы рисунки оказались в одном каталоге с таблицей ThemeCSS.css
Откройте страницу ThemeCSS.aspx на редактирование, удалите в ней <link> подключения внешней <head > является серверным
Исполните страницу и убедитесь, что стили пока не действуют, потому что не подключеныТеперь только осталось подключить тему MyTheme к странице.
В панели Properties выделите объект DOCUMENT и установите его свойство Theme в значение MyTheme
Выполните страницу ThemeCSS.aspx и убедитесь, что стили из внешней таблицы ThemeCSS.css работают
Назначьте страницу TestCSS.aspx, где мы CSS использовали напрямую, стартовой и выполните ееЧтобы сделать некоторые выводы, сравним полученные результаты, приведенные ниже в уменьшенном виде.
![]() |
![]() |
| Используется только |
Используется |
Выводы:
<link> ссылку на внешнюю CSS. Теперь осталось проверить тот факт, что ASP.NET подключает к странице все
В каталоге Theme сделайте еще три копии файла ThemeCSS.css с именем ThemeCSS1.css , ThemeCSS2.css , ThemeCSS3.css
Назначьте страницу ThemeCSS.aspx стартовой и выполните ее
На появившемся окне Исследуем блок кода заголовочного <. Он будет содержать такие строки
<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 автоматически вставляет в код столько
Удалите лишние файлы ThemeCSS1.css, ThemeCSS2.css и ThemeCSS3.css, чтобы они дальше не мельтешили у нас в глазахДо сих пор мы спокойно удаляли файл web.config приложения с уверенностью, что он будет вновь создан оболочкой. Тем более, что там содержалась только заготовка кода. Теперь пришла пора редактировать этот файл и удалять его уже будет жалко.
Ранее мы говорили, что при подключении к странице темы (в наших примерах - MyTheme ) через свойство объекта DOCUMENT оболочка автоматически вставляет соответствующий атрибут в @Page этой страницы, тем самым подключая к странице индивидуальную тему.
Например
<% @Page Language="C#" Theme="MyTheme" %>
Обычно проектировщики ратуют за одинаковое стилевое оформление страниц и используют в каждой из них одну и ту же тему. В этом случае удобнее будет не подключать каждую страницу к одной и той же теме, а указать общую тему в
Откройте страницы наших примеров, использующих темы, а именно: TestTheme.aspx, TestCalendar.aspx, ThemeCSS.aspx, и удалите в них из @Page атрибут Theme ="MyTheme"
Назначая каждую страницу стартовой, исполните их по очереди, чтобы убедиться, что отключенная тема в них не действует. Пока получилась грустная, унылая картина
Откройте на редактирование заготовку файла web.config, автоматически созданную оболочкой
Отредактируйте код файла web.config, добавив всего один <pages theme ="MyTheme" />, и сохраните изменения на дискеНиже приведен окончательный код файла web.config с указанием общей темы по умолчанию, в котором убраны громоздкие комментарии и пустые
<?xml version="1.0"?> <configuration> <system.web> <compilation debug="true"/> <authentication mode="Windows"/> <pages theme="MyTheme" /> </system.web> </configuration>
Назначая каждую из перечисленных выше страниц стартовой, вновь исполните их по очереди, чтобы убедиться, что тема опять заработала так, как будто-бы она была индивидуально подключена к каждой страницеЕсли нужно сделать так, чтобы общая тема действовала по умолчанию на множестве страниц, но не перезаписывала на них индивидуальные стилевые настройки элементов управления, то
<?xml version="1.0"?> <configuration> <system.web> <compilation debug="true"/> <authentication mode="Windows"/> <pages styleSheetTheme="MyTheme" /> </system.web> </configuration>
Если на какой-нибудь странице нужно сделать так, чтобы общая тема не действовала на нее по умолчанию, то есть два варианта:
@Page атрибут Theme ="Другая_тема"@Page страницы нужно вставить атрибут EnableTheming="false"<link> или в EnableTheming="false" отключает только skin -файлы, CSS все равно останется подключенной.Во всех наших примерах мы создавали активные страницы в корневом виртуальном каталоге сайта. Но для сайта с тысячами страниц это неприемлемый способ. Страницы могут группироваться (брыкаться, кусаться, кричать "Я пойду жаловаться в обком!") по любому признаку, например тематическому, и размещаться в отдельных папках развитой древовидной системы виртуальных каталогов. Корнем этого дерева должен быть виртуальный каталог сайта, его еще называют корнем Web-дерева.
В развитом Web-дереве применение общей темы по умолчанию является удобным способом стилизации страниц. В каждом каталоге можно разместить отдельный файл web.config со своей общей темой и все страницы этого каталога будут использовать эту тему по умолчанию.
До сих пор мы рассматривали случай, когда разработчик сам жестко привязывает тему к странице или группе страниц. Но иногда (для крутизны) может возникнуть необходимость поручить выбор темы для конкретной страницы пользователю с немедленным изменением ее стилевого оформления. При этом неважно, была ли включена на странице индивидуальная тема или по умолчанию применялась тема конфигурационного файла.
Все, что нужно сделать, это предусмотреть на странице интерфейс выбора темы, а в коде страницы динамически присвоить свойству Page. или Page.StyleSheetTheme выбранное пользователем значение. При этом важно понимать, что тема настраивается перед инициализацией страницы, поэтому соответствующий код нужно поместить в обработчик Page_PreInit(). Если это сделать позже, в обработчиках других событий, то попытка присвоить новое значение свойству Page. или Page.StyleSheetTheme вызовет ошибку компиляции.
С другой стороны, прочитать выбор пользователя можно только после создания страницы, когда присваивать свойству темы новое значение уже поздно. Поэтому динамическое задание темы нужно выполнять в два этапа:
Page_PreInit() назначить новую темуПри перезапуске страницы она должна быть переадресована на саму себя. Такую операцию можно выполнить либо методом , либо методом Server.. Первый метод реализует полный цикл с отправкой на Server.!
Рассмотрим все это на примере. Прежде всего, нужно создать несколько тем, чтобы было из чего пользователю выбирать.
В панели Sulution Explorer вызовите контекстное меню для папки MyTheme и выполните команду Copy
В панели Sulution Explorer вызовите контекстное меню для папки App_Themes, где должны храниться все темы приложения, и выполните на ней команду Paste два раза, чтобы создать еще две темы
Присвойте копиям такие замысловатые имена, какие давали нам в глубоком детстве на улице у родного батюшки, например, MyTheme1 и MyTheme2Обратите внимание, что новые темы имеют старое содержание, которое было бы желательно подправить, чтобы наглядно видеть влияние выбранной темы на оформление страницы. Мы это сделаем попозже и помягше - об чем должна болеть голова, прежде всего, у нашего дизайнера ( за што ему, акаянному, только деньги плотють ). Наше дело - режь, клей и запускай. Студент Зиборов! - и... чтобы еще работало!
Учитывая, что протокол HTTP не поддерживает сохранение состояний и что страница существует только на время обработки обратной отсылки, выбранную пользователем тему нужно где-то сохранять. Это могут быть cookie -наборы ( куки -файлы) на компьютере клиента, которые мы туда запишем без его ведома, если он забыл выключить их поддержку. Это могут быть ), которые мы будем пересылать туда-сюда. Это могут быть глобальные объекты уровня сеанса или приложения, которые существуют на сервере, пока не закончится сеанс с пользователем или не закроется ( на обед или профилактику ) приложение. Мы выбираем свободу, демократию и объект уровня сеанса !
Через панель Solution Explorer копируйте в корневой виртуальный каталог нашего сайта с примерами файл TestTheme.aspx и назовите его TestSwitchThemes.aspx
Определите новую страницу TestSwitchThemes.aspx стартовой
Откройте файл TestSwitchThemes.aspx на редактирование и добавьте в верхнюю часть страницы из вкладки Standard элемент пользовательского интерфейса для выбора темы, раскрывающийся список DropDownList
Переименуйте ID списка в lstSwitchThemes
Через панель Properties в режиме Events создайте для списка заготовку обработчика события SelectedIndexChanged, которое поступит на сервер с обратной отсылкой, если пользователь изменит выбор в списке
Добавьте на страницу перед списком серверный элемент Label с именем lblFirstLoadНа всякий пожарный случай (чтобы вам - его скопировать, а мне - отчитаться по объему текста перед зав. кафедрой Горенским Б.М.), приведу полный дескрипторный код, который будет иметь страница после проведения последних "оперативно-следственных" мероприятий
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="TestSwitchThemes.aspx.cs" Inherits="TestTheme" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Тест применения тем</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="lblFirstLoad" runat="server" Text="Label" />
<asp:DropDownList ID="lstSwitchThemes" runat="server"
OnSelectedIndexChanged="lstSwitchThemes_SelectedIndexChanged">
</asp:DropDownList>
<br />
<br />
<asp:BulletedList ID="BulletedList1" runat="server">
<asp:ListItem>Туризм</asp:ListItem>
<asp:ListItem>Спорт</asp:ListItem>
<asp:ListItem>Музыка</asp:ListItem>
<asp:ListItem>Танцы</asp:ListItem>
</asp:BulletedList>
<asp:Label ID="Label1" runat="server" Text="Текстовая метка" />
<asp:CheckBox ID="CheckBox1" runat="server" Text="Флажок"
BackColor="Black" ForeColor="Yellow" EnableTheming="True" />
<br />
<br />
<b>Тема подключена к странице через свойство Theme объекта DOCUMENT</b>
<br />
<table width="100%" border="1">
<tr>
<td>
SkinID не подключен: действуют общие настройки по умолчанию
</td>
<td>
<asp:Label ID="Label2" runat="server" Text="Label2" />
</td>
<td>
<asp:CheckBox ID="CheckBox2" runat="server" Text="CheckBox2" />
</td>
</tr>
<tr>
<td>
Именованные настройки подключены: SkinID="Variant3"
</td>
<td>
<asp:Label ID="Label3" runat="server" Text="Label3"
SkinID="Variant3" />
</td>
<td>
<asp:CheckBox ID="CheckBox3" runat="server"
Text="CheckBox3" SkinID="Variant3" />
</td>
</tr>
<tr>
<td>
Именованные настройки подключены: SkinID="Variant4"
</td>
<td>
<asp:Label ID="Label4" runat="server" Text="Label4"
SkinID="Variant4" />
</td>
<td>
<asp:CheckBox ID="CheckBox4" runat="server" Text="CheckBox4"
SkinID="Variant4" />
</td>
</tr>
<tr>
<td>
SkinID="Variant5" подключен, но тема подавлена: EnableTheming="False"
</td>
<td>
<asp:Label ID="Label5" runat="server" Text="Label5"
EnableTheming="False" SkinID="Variant5" />
</td>
<td>
<asp:CheckBox ID="CheckBox5" runat="server" Text="CheckBox5"
EnableTheming="False" SkinID="Variant5" />
</td>
</tr>
<tr>
<td>
Подключен несуществующий SkinID="XXX": настройки темы не действуют
</td>
<td>
<asp:Label ID="Label6" runat="server" Text="Label6"
SkinID="XXX" />
</td>
<td>
<asp:CheckBox ID="CheckBox6" runat="server" Text="CheckBox6"
SkinID="XXX" />
</td>
</tr>
</table>
<br />
<asp:Button ID="Button1" runat="server" Text="Отправить" />
</div>
</form>
</body>
</html>
Откройте на редактирование файл кода TestSwitchThemes.aspx.cs и заполните его такusing System;
//using System.Data;
//using System.Configuration;
//using System.Collections;
//using System.Web;
//using System.Web.Security;
//using System.Web.UI;
//using System.Web.UI.WebControls;
//using System.Web.UI.WebControls.WebParts;
//using System.Web.UI.HtmlControls;
public partial class TestTheme : 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);
}
}
Прежде, чем выполнить страницу, сделаем некоторые пояснения по приведенному C#-коду
DirectoryInfo мы явно указали с пространством имен System.IO и компилятор его увидитSession , Server, Response , Request являются общедоступными System.Web.UI.Page, который наследуется нашим классом TestTheme, а значит явно преобретает все эти свойстваSystem только потому, что в коде имеются ключевые слова string, int, bool, используемые при явном System.string, System.int, System.boolТеперь осталось внести какое-либо видимое различие в оформления тем, чтобы мы могли убедиться, что программно была подключена действительно другая тема. Для экономии своих сил внесем минимальные изменения, например, сделаем разными
Вызовите на редактирование файл App_Themes/MyTheme1/ThemeCSS.css и поменяйте в селекторе
Вызовите на редактирование файл App_Themes/MyTheme2/ThemeCSS.css и поменяйте в селекторе Наступил момент истины...
Исполните страницу и убедитесь в справедливости сказанного. Должен получиться такой уменьшенный результат![]() |
![]() |
![]() |
Подобным образом программно можно менять и другие стилевые свойства страницы и ее элементов, например, именованные оформления элементов управления, определенные атрибутом SkinID. Не обязательно давать пользователю возможность настройки стилевого оформления напрямую. Можно сделать оформление страниц и элементов косвенно зависимым от выбора пользователя. Принципиальной разницы с точки зрения кода здесь мало, главное - не переусердствовать!
И последнее... Все, что было сказано выше для декларативного способа подключения тем и приоритетов их применения, остается справедливым и для
Вот и закончилась тема про "темы"!
Очень часто требуется зафиксировать структуру страницы так, чтобы одни и те же элементы управления пользовательского интерфейса размещались в одном и том же месте как на одной странице, так и на множестве страниц сайта. Это позволяют сделать специальные страницы - шаблоны, которые существуют независимо, но подключаются к страницам по мере необходимости. Любая исполнимая страница может подключать только один из заранее заготовленных шаблонов.
Шаблон размечает
Перекомпоновка подключенного шаблона или его содержимого, а также подключение к исполнимой странице нового шаблона на
Исполнимая страница получает от используемого шаблона его

Шаблоны представляют собой обычные страницы, за исключением нескольких отличий:
@Page используется @Master System.Web.UI.MasterPage , вместо System.Web.UI.Page для обычной исполнимой страницыContentPlaceHolder используется для резервирования ContentPlaceHolder можно размещать в ячейках таблицы. При выполнении эти ячейки заполнятся Шаблон представляет собой полноценную страницу, готовую к выполнению, но не самостоятельно, а через исполнимую страницу содержимого. Оболочка имеет мастер для создания заготовок шаблонов, как и обычных страниц. Для примера, давайте создадим простую эталонную шаблон-страницу и пустую (вначале) исполнимую страницу, чтобы испытать шаблон.
Добавьте к проекту командой 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
Удалите ContentPlaceHolder и через контекстное меню редактора выполните команду Add Content Page (добавить страницу содержимого)
Оболочка сгенерирует такую заготовку файла Default.aspx
<%@ Page Language="C#"
MasterPageFile="~/FirstMasterPage.master"
AutoEventWireup="true" CodeFile="Default.aspx.cs"
Inherits="_Default" Title="Тестовая страница содержимого" %>
<%-- Add content controls here --%>
Пустой файл, - только @Page страницы со стандартными атрибутами страницы и атрибутом подключения шаблона.
<%--...--%> в дескрипторный код файлов ASP.NETОболочка прописала значение атрибута подключения MasterPageFile с путем относительно корня Web-дерева нашего сайта (ну, там наш шаблон и находится). Если уже подключенный к каким-то страницам шаблон переместить из корня в другую папку Web-дерева, то оболочка не меняет автоматически путь атрибута MasterPageFile во всех ссылающихся на шаблон страницах, это придется делать вручную (ох и работы, можно запутаться!). Поэтому нужно заранее спланировать, будем ли мы использовать
Создайте в панели Solution Explorer через контекстное меню для Web-корня подпапку MasterPages командой New Folder
Переместите мышью в папку MasterPages шаблон FirstMasterPage.master Теперь давайте откорректируем дескрипторный код исполнимой страницы.
В панели Solution Explorer дайте файлу Default.aspx новое имя FirstMasterPage.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, включенной нами ранее в
<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 текстовую строку, чтобы дескрипторный код стал таким(рис ) Дескрипторный код шаблона 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">
<h1>Привет студентам из "именованной области1" мастер-страницы!</h1>
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Перейдите в режим Теперь нужно настроить страницу содержимого, использующую шаблон.
Откройте на редактирование в режиме Source страницу содержимого FirstMasterPage.aspx, к которой подключен шаблон, и определите в контейнере <asp :Content > атрибуты ID самого ContentPlaceHolderID подключенного шаблона, на которую будет ссылаться Идентификатор ID самого контейнера < в странице содержимого определять необязательно, если только мы не планируем управлять им программно. Измененный код будет таким
<%@ 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>
Исполните страницу
Поместите на шаблон еще один контейнер шаблона ContentPlaceHolder и наполните его таким кодом(рис ) Дескрипторный код шаблона 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">
<h1>Привет студентам из "именованной области1" мастер-страницы!</h1>
</asp:ContentPlaceHolder>
<br />
<asp:ContentPlaceHolder ID="ContentPlaceHolder2" runat="server">
<h1>Привет студентам из "именованной области2" мастер-страницы!</h1>
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Перейдите на страницу содержимого Мы видим, что
Мы можем рассматривать итоговую страницу пользователя как двухслойную. На нижнем слое находится
Иными словами, именованная область шаблона спроецируется на итоговую страницу всегда: либо с содержимым (в том числе пустым) прикрепленного к ней контейнера, либо со своим содержимым (при его наличии), если для нее нет прикрепленного контейнера. О пустых полях внизу областей беспокоиться не нужно. На этапе выполнения они исчезнут. Просто, оболочка выделяет минимально необходимую
Обратите внимание на заголовки
Давайте добавим контейнер содержимого к нижней
На странице FirstMasterPage.aspx в режиме Design вызовите контекстное меню для нижней Оболочка добавит пустой контейнер содержимого и автоматически свяжет его в дескрипторном коде с именованной областью. Отсюда еще одна мораль:

После того, как на вновь созданной странице с содержимым проявятся
Если
Приведем более содержательный пример разработки страниц с использованием шаблонов. Учитывая, что HTML поддерживает только потоковую
В панели Solution Explorer вызовите контекстное меню для папки MasterPages, которую мы создали ранее, и выполните команду Add New Item
В окне мастера создания заготовок выберите шаблон Master Page и создайте эталонную страницу с именем Title .master без файла отделенного кода
Оболочка добавит заготовку эталонной страницы в каталог MasterPages, где ей и место.
Переведите в редакторе эталонную страницу Title.master в режим Design и удалите пока автоматически созданный экземпляр элемента ContentPlaceHolder (чтобы не путался под ногами)
В режиме Design из вкладки Standard панели Toolbox поместите в самом начале Image как контейнер для размещения ID="ImageBanner"Замечание. Элемент из вкладки HTML не будет проявляться на странице содержимого, потому что не обрабатывается сервером (если только ему не присвоить атрибут runat="server" )
Вызовите контекстное меню для папки MasterPages и выполните команду Add Existing Item. Найдите через открывшееся диалоговое окно файл Banner.png, который находится в прилагаемом к данной работе каталоге Pictures, и скопируйте его в папку MasterPages текущего сайта
Выделите экземпляр ImageBanner и присоедините к нему через свойство ImageUrl рисунок Banner.png из папки MasterPages Web-дерева сайта. Наш
Разместите после <h1 style="color: Green">
Мы приветствуем Вас на нашем сайте!!!
</h1>
Элемент шаблона ContentPlaceHolder по умолчанию растягивается по всей ширине страницы. Чтобы позиционировать его на

В трех ячейках таблицы будет размещаться потенциально заменяемое содержимое ContentPlaceHolder. В разных ячейках таблицы мы сделали разный фон только для учебных целей, чтобы сделать ячейки видимыми и показать, что фон ячеек таблицы с
Мы должны четко представлять, что элементы управления ContentPlaceHolder и являются прозрачными контейнерами для своего содержимого, если только мы искусстенно не создадим в них фон другими элементами, например, элементом , , Table. Поэтому, если мы на странице содержимого не создадим свой фон в замещающих элементах , то будет проявляться в итоговой странице фон элемента-контейнера
Поместите на Table
Используя боковые маркеры таблицы и команды меню Layout оболочки, постройте таблицу из трех строк и двух столбцов, чтобы она соответстворвала приведенному выше рисункуРекламация Большому Биллу: Мы конечно осознаем все революционные возможности Visual Studio 2005 по разработке программ. Но нас-то тоже нужно понять, мы привыкли к развитым
В конечном виде таблица вместе с вутренними стилями должна описываться следующими
<table border="0" width="100%">
<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 , к которому мы присоединим рисунок, задающий фон ячейки. ID=Panel1 копии этого элемента изменять не будем, поскольку не планируем в дальнейшем им программно управлять
Задайте для созданного экземпляра элемента управления Panel значения свойств: Width=100%; Height =100%, чтобы элемент полностью занял верхнюю ячейку таблицы
Через проводник Windows найдите в прилагаемом к данной работе каталоге Pictures файл BackTitleSrc.jpg и в любом Рисунок не должен быть слишком большим, чтобы "не застрял в проводах" по пути к пользователю.
В панели Solution Explorer в контекстном меню для папки MasterPages выполните команду Add Existing Item, найдите ваш рисунок BackTitle.jpg и скопируйте его в эту папку
Выделите на странице экземпляр Panel1 в верхней строке таблицы и через панель инструментов Properties присоедините в свойстве BackImageUrl этот рисунок, который многократным повторением займет всю Panel1Теперь можно разместить в ячейках таблицы прозрачные контейнеры-шаблоны элемента управления ContentPlaceHolder.
Поместите из вкладки Standard панели Toolbox в верхнюю строку таблицы в объект Panel1 элемент-контейнер ContentPlaceHolder, который будет представлять на странице ContentPlaceHolder1 для размещения
То же самое сделайте для правой_средней и нижней ячеек таблицы
В контейнер ContentPlaceHolder1 вставьте и отредактируйте такую строку<div style="font-weight: bold; font-size: xx-large; color: red; text-align: center">
Сведения об автошколе в целом
</div>
Вставьте в правый контейнер ContentPlaceHolder2 любой текст, например, такой или его частьВот уже более 12 лет мы занимаемся подготовкой водителей
категории "B" в г.Красноярске и всегда занимали первые места
в сводках МРЭО ГИБДД по качеству обучения. Автошкола всегда нацелена
на успех наших клиентов в сдаче экзаменов ГАИ с первого раза
и своевременном получении водительского удостоверения.
Мы обеспечиваем максимальные удобства своим клиентам. Для
этого существуют вечерняя, воскресная и заочная формы обучения.
Наши курсанты имеют возможность бесплатно и неограниченно пользоваться
компьютерным классом. Учебные автомобили прибывают по заявке
клиента к назначенному им месту. Развивается сеть филиалов автошколы
в г.Красноярске.
Наша компьютерная экзаменационная программа успешно используется
в ГИБДД г.Красноярска, Железногорска, Назарово, Емельяново, Шарыпово
для государственной аттестации кандидатов в водители. Мы неоднократно
выпускали цветные учебно-методические пособия по Правилам дорожного
движения, которыми постоянно пользуются большинство автошкол
города и края.
Лекционные занятия в автошколе ведут квалифицированные преподаватели
с учеными степенями и званиями с применением современных компьютерных
технологий. Комплексный подход к обучению и разнообразие форм
позволяют максимально сократить усилия наших клиентов и сроки
усвоения ими учебного материала. Парк учебных автомобилей насчитывает
более 15 штук, включая иномарки.
В нижний контейнер ContentPlaceHolder3, резервирующий место под <strong> Автошкола Диалог-Сервис в целом работает без перерыва на обед и выходных с 8 часов утра до 9 часов вечера!!! </strong>
Поместите в левую ячейку таблицы надпись, а из вкладки Standard панели Toolbox три HyperLink Дескрипторный код содержимого левой ячейки таблицы будет примерно таким
<td style="width: 25%; background-color: #9DFF7E" valign="top">
<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>
</td>
Сейчас мы пока не определяем в гиперссылках элементы
Все, таблицу мы заполнили. Попробуем разместить еще что-нибудь ниже таблицы, например, товарный знак и страшилку от воров интеллектуальной собственности! Хотя, мы сами ее воруем у других, будут воровать и у нас.
Отступите ниже таблицы одну-две строчки и добавьте из вкладки HTML панели Toolbox элемент управления Image . Щелкните на нем правой кнопкой мыши и выполните команду Run As Server Control, чтобы содержимое элемента проявилось в будущем на странице содержимого
В панели Solution Explorer вызовите контекстное меню для папки MasterPages и скопируйте в проект командой Add Existing Item из прилагаемого каталога Pictures рисунок 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 2007
</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>
Наступил момент истины! Пора тиражировать страницы содержимого на базе созданной
Мы для нашего примера создадим 4 страницы содержимого с простыми именами:
Satellites.aspx - первая страница, главная, не будет иметь свое содержимое, значит вся мастер страница проявится на выходе. Остальные три страницы будут переопределять все шаблоны Satellite1.aspx - будет вызываться по первой ссылке в разделе "Наши филиалы" и переопределять содержимое всех контейнеров, кроме Satellite2.aspx - будет вызываться по второй ссылке в разделе "Наши филиалы"Satellite3.aspx - будет вызываться по третьей ссылке в разделе "Наши филиалы"Есть несколько способов создания
В панели Solution Explorer выделите корень Web-дерева и выполните команду меню Website/Add New Item (или команду Add New Item контекстного меню)
В появившемся диалоговом окне отметьте показанные настройки, включая
В следующем окне выберите 
Созданная страница добавится в корень Web-дерева и будет содержать контейнеры с подключенным пустым содержимым для всех шаблонов выбранной
В панели Solution Explorer выделите нужную Будет создана страница содержимого, размещенная в том же каталоге, что и выделенная MasterPageFile будет прописан относительно корня Web-дерева, например,
MasterPageFile="~/ - (как-бы абсолютный адрес в пределах сайта)
Это значит, что мы можем переместить страницу содержимого в любую папку в пределах Web-дерева, и везде адрес
Откройте Обратите внимание, что двумя последними способами страница создается без отдельного файла поддержки C#. Это легко исправить, добавив к проекту файл .cs с предшествующим именем страницы. Правда, оболочка при этом спросит, создавать ли для этого класса отдельную папку со стандартным именем App_Code, на что нужно ответить Нет. И еще, при таком способе добавления к странице файла поддержки нужно вручную прописать необходимые атрибуты в декларации @Page
AutoEventWireup="true" CodeFile="XXX.aspx.cs" Inherits="YYY"
Вернемся к нашему примеру. Мы не собираемся программно управлять нашими страницами при иллюстрации рассматриваемой темы
Щелкните правой кнопкой мыши на открытой
Переименуйте страницу Default.aspx в Satellite .aspx и переместите ее в корневую папку Web-дерева
Подобным же образом создайте и переместите в корень остальные страницы содержимого: Satellite1.aspx, Satellite2.aspx, Satellite3.aspx. Но можно просто раскопировать в корне в трех экземплярах файл Satellite.aspx, учитывая, что все страницы будут ссылаться на одну и туже Теперь давайте корректировать заготовки страниц содержимого. Но прежде всего нужно доделать нашу
Выполните команду Window/Close All Documents, чтобы закрыть все редактируемые на текущий момент файлы
В панели Solution Explorer щелкните правой кнопкой мыши на файле ~/MasterPages/Title.master и выполните команду View Designer, чтобы открыть
Поочередно выделяя элементы гиперссылок, установите их свойство NavigateUrl на соответствующие страницы содержимого Satellite1.aspx, Satellite2.aspx, Satellite3.aspx. Сохраните и закройте Отредактируем страницы содержимого, начнем с Satellite.aspx
В панели Solution Explorer назначьте страницу Satellite.aspx стартовой и откройте ее на редактирование в режиме DesignЧто мы видим на данном этапе времени проектирования:
Удалите все контейнеры содержимого из страницы Satellite.aspx, оставьте только строку с @Page. Эта страница у нас будет стартовой и своего содержимого иметь не будет
Перейдите на странице Satellite.aspx в режим Design и мы видим, что проявилось и содержимое шаблонов
Исполните страницу
Пощелкайте по ссылкам и обратите внимание, как меняется адрес в Теперь нужно наполнить страницы ссылок индивидуальным содержимым.
Приведем окончательный вариант дескрипторного кода для всех страниц данного примера
ContentPlaceHolder должны находиться внутри <form></form>!<%@ Master Language="C#" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div style="text-align: center">
<asp:Image ID="ImageBanner" runat="server" ImageUrl="~/MasterPages/Banner.png" />
<h1 style="color: Green">
Мы приветствуем Вас на нашем сайте!!!
</h1>
<br />
<table border="0" width="100%">
<tr>
<td colspan="2">
<asp:Panel ID="Panel1" runat="server" Height="100%" Width="100%" BackImageUrl="~/MasterPages/BackTitle.jpg">
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
<div style="font-weight: bold; font-size: xx-large; color: red; text-align: center">
Сведения об автошколе в целом
</div>
</asp:ContentPlaceHolder>
</asp:Panel>
</td>
</tr>
<tr>
<td style="width: 25%; background-color: #9DFF7E" valign="top">
<strong style="color: Blue">Наши филиалы:</strong><br />
<br />
<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="~/Satellite1.aspx">Ленинский район</asp:HyperLink><br />
<br />
<asp:HyperLink ID="HyperLink2" runat="server" NavigateUrl="~/Satellite2.aspx">Центральный район</asp:HyperLink><br />
<br />
<asp:HyperLink ID="HyperLink3" runat="server" NavigateUrl="~/Satellite3.aspx">Свердловский район</asp:HyperLink>
</td>
<td style="background-color: #FFB8FF">
<asp:ContentPlaceHolder ID="ContentPlaceHolder2" runat="server">
Вот уже более 12 лет мы занимаемся подготовкой водителей категории "B" в г.Красноярске
и всегда занимали первые места в сводках МРЭО ГИБДД по качеству обучения. Автошкола
всегда нацелена на успех наших клиентов в сдаче экзаменов ГАИ с первого раза и своевременном
получении водительского удостоверения.
<br />
<br />
Мы обеспечиваем максимальные удобства своим клиентам. Для этого существуют вечерняя,
воскресная и заочная формы обучения. Наши курсанты имеют возможность бесплатно и
неограниченно пользоваться компьютерным классом. Учебные автомобили прибывают по
заявке клиента к назначенному им месту. Развивается сеть филиалов автошколы в г.Красноярске.
</asp:ContentPlaceHolder>
</td>
</tr>
<tr style="background-color: #FFFF92">
<td colspan="2">
<asp:ContentPlaceHolder ID="ContentPlaceHolder3" runat="server">
<strong>Автошкола Диалог-Сервис в целом работает без перерыва
на обед и выходных с 8 часов утра до 9 часов вечера!!!
</strong>
</asp:ContentPlaceHolder>
</td>
</tr>
</table>
<p style="text-align: right; color: Blue; font-family: 'Courier New'; font: bold italic">
<img id="IMG1" runat="server" src="LIGHT.ICO" />
ampnbsp;Copyright © 2007</p>
<asp:ContentPlaceHolder ID="ContentPlaceHolder4" runat="server">
<strong><em>Вы уж, пожалуйста, наведывайтесь к нам почаще!</em></strong>
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Все контейнеры < уничтожены, поэтому страница используется только как запускающая и не добавляет к
<%@ 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.Init Page.Init страницы содержимогоPage.Load Такой порядок означает, что если мы программно меняем одни и те же настройки в
< обычной страницы, где можно задавать все составляющие его <, добавив в @Page атрибут страницы содержимого. В этом случае <
Программно можно переопределять не только <, но и другие < < 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 переопределить <
<%@ Page Language="C#" MasterPageFile="~/MasterPages/Title.master"
Title="Untitled Page" %>
Замените атрибут Title @Page на следующий(рис ) Файл SatelliteExt.aspx<%@ Page Language="C#" MasterPageFile="~/MasterPages/Title.master"
Title="Декларативный заголовок SatelliteExt.aspx" %>
Исполните страницу - результат будет таким
Поскольку мы не создавали для страницы SatelliteExt.aspx отдельный файл кода поддержки, то код переопределения заголовка будем писать в скриптах страницы
Переведите страницу SatelliteExt.aspx в режим Design и щелкните дважды на притушенной области проступающего заполнителя Оболочка автоматически создаст блок скрипта и вставит в него заготовку обработчика события Page..
Заполните обработчик так(рис ) Файл SatelliteExt.aspx после добавления обработчика 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>
Исполните страницу - результат будет таким
Несмотря на то, что мы оставили декларативный атрибут , обработчик переопределил его в окончательном выводе. Это и понятно: декларативный атрибут инициируется при создании объекта заголовка, а обработчик 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 и будем обращаться к нему напрямую
(рис ) Добавление свойства доступа к дескриптору <h1> в файле Title.master<%@ 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 следующим кодом(рис ) Дополненный код страницы содержимого 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 и убедитесь, что @ MasterType указывает ASP.NET виртуальный путь к соответствующему файлу
Измените страницу содержимого SatelliteExt.aspx следующим образом(рис ) Измененный код страницы содержимого 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 и убедитесь, что Второй способ более предпочтительный, поскольку мы не вмешиваемся в код спроектированной
Иногда может возникнуть необходимость дать возможность пользователю подключать необходимые Page. в @Page. Теперь нам нужно программно менять атрибут Page.MasterPageFile.
Здесь нужно иметь ввиду следующее:
ContentPlaceHolderIDPage.PreInit страницы содержимого. Если это сделать в обработчиках более поздних событий, то будет сгенерировано исключениеVIEWSTATE ), глобальные объекты уровня сеанса или приложенияУчитывая, что наши страницы Satellite.aspx, Satellite1.aspx, Satellite2.aspx, Satellite3.aspx согласованы с Title.master, сделаем их копии и настроим под динамическую смену
Откройте ImageBanner (после открывающего <div> ) элемент ContentPlaceHolder с именем ContentPlaceHolderList. Сохраните и закройте файл Title.master
Сделайте копии соответствующих файлов и присвойте им имена Title1.master , SatelliteDynamic.aspx, SatelliteDynamic1.aspx, SatelliteDynamic2.aspx, SatelliteDynamic3.aspx
Определите страницу SatelliteDynamic.aspx стартовой
Откройте <script runat="server">...</script >ImageBanner и внесите еще какие-нибудь визуально отличимые измененияHyperLink еще одну с названием "Автошкола в целом"NavigateUrl гиперссылок значениями новых страниц содержимого
Откройте страницу содержимого SatelliteDynamic.aspx и в режиме Design создайте контейнер содержимого для шаблона ContentPlaceHolderList, выполнив на нем команду Create Custom Content контекстного меню
Добавьте в контейнер содержимого предваряющий текст "Выберите мастер-страницу :" и элемент DropDownList с именем lstMasterPages
Заполните раскрывающийся список
Items[0]Items[1]
Установите для списка lstMasterPages свойство AutoPostBack ="True"
В режиме Design Page_Load() и переименуйте его в Page_Init()
Скопируйте заготовку обработчика Page_Init() и переименуйте копию в Page_PreInit(), поскольку все они имеют одинаковую
В режиме Design lstMasterPages списка создайте обработчик изменения выбора опции lstMasterPages_SelectedIndexChanged()
Заполните обработчики так, чтобы окончательный код страницы был таким(рис ) Окончательный код страницы SatelliteDynamic.aspx<%@ Page Language="C#" MasterPageFile="~/MasterPages/Title.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 и добавьте в каждый из них после @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-дерева
Код страницы сделайте таким(рис ) Дескрипторный код страницы MasterPageLevel1.master<%@ Master Language="C#" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div style="text-align: center; color: #0000ff">
<h1>
Мастер-страница уровня Level1 - наибольшей глубины.
Ее можно использовать как верхний колонтитул
</h1>
<asp:ContentPlaceHolder ID="ContentPlaceHolderLevel1" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Теперь создайте MasterPageLevel0.master и подключите к ней предыдущую через атрибут MasterPageFile @Master Код страницы должен выглядеть так
<%@ Master Language="C#" MasterPageFile="~/MasterPageLevel1.master" %>
<asp:Content ID="ContentLevel0" ContentPlaceHolderID="ContentPlaceHolderLevel1" runat="server">
<table width="100%" 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>
Выполните для страницы MasterPageLevel0.master команду Website/Add Content Page, чтобы создать для нее страницу содержимого
Измените имя по умолчанию Default.aspx созданной страницы содержимого на TestMasterPageLevel.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 нельзя!
Для страниц, которые не имеют подключения MasterPageFile, можно задать
<configuration> <system.web> <pages masterPageFile="XXX.master" /> </system.web> </configuration>
Этот подход не считается надежным, поскольку требует строгого согласования всех страниц содержимого с шаблонами одной
Ну вот и приплыли, граждане студенты. До сих пор я писал изложение, а вы его читали. Теперь вы будете писать сочинение, а я его буду смотреть в аттестационную и зачетную недели! Отсюда вам мой наказ (читай "Указ!"):
Единообразие в оформлении множества отдельных страниц сайта является важной его характеристикой. Visual Studio 2005 имеет три возможности для поддержки форматирования сайта:
Применение стандартизации требует прежде всего выработать единообразный визуальный
Это старое средство форматирования, которое входит в HTML4 и поддерживается практически всеми
<head > и имеет описание стилей общее для тех По отношению к этим трем типам CSS также соблюдается свойство каскадности, т.е. стиль внутреннего каскада имеет более высокий приоритет и перекрывает действие внешнего стиля. Поскольку задачей нашего курса является не только изучение возможностей Visual Studio 2005 в Web-программировании, рассмотрим кратко все перечисленные типы CSS.
Хотя CSS обычно не применяется для изменения вида каждого тега в отдельности, но принципиально можно это делать, особенно, когда нужно перекрыть действие внешнего каскада стиля для конкретного <h1> будет таким

Определенный в
Пусть отдельный заголовочный
<h1 style="color:red; text-align:center">Этот заголовочный текст будет центрирован в текущем документе и иметь красный цвет (бледный вид)!</h1>
Отклик
Определение внутренних стилей отдельных < в своем дескрипторном блоке <. Синтаксис встроенных стилей следующий

Атрибут type="text/ body и h1 совпадают с именами
Имена классов ".имя_класса" выбираются произвольно. В том class="имя_класса". Классы для конкретного вида тегов "тег.имя_класса" используются только в тегах заданного типа по той же самой схеме class="имя_класса".
Пусть страница имеет код, приведенный ниже (файл embedded.htm в каталоге CSS рассматриваемой темы)
<html>
<head>
<title>Документ со встроенной CSS</title>
<meta content="text/html; charset=windows-1251" http-equiv="Content-Type">
<style type="text/css">
body
{
background:white url(MyWeb.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>
</head>
<body>
<h1>
Заполните анкету!</h1>
<form>
<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-документу выполняется добавлением в блок < <link> или @import.
Пусть имеется два файла с внешними стилями и произвольными именами, например, и default.. Вот варианты их подключения в HTML-документ MyPage. ( обязательно в заголовочный блок < ):
| Вариант | В блоке < |
Замечания |
|---|---|---|
| Подключается одна |
<link rel="stylesheet" href="header.css"> |
|
| Подключается две |
<link rel="stylesheet" href="header.css"> <link rel="stylesheet" href="default.css"> |
|
| Подключается одна |
<style type="text/css">
@import url(header.css);
</style>
|
Не поддерживается |
| Подключается две |
<style type="text/css">
@import url(header.css);
@import url(default.css);
</style>
|
Не поддерживается |
| Подключается две |
<style type="text/css">
@import url(header.css);
</style>
|
В самом начале файла header.css имеется голая строка прямого подключения:@import url(default.css) |
| Подключается две |
<style type="text/css">
@import url(header.css);
</style>
<link rel="stylesheet" href="default.css">
|
Порядок следования не влияет |
| Подключается две |
<link rel="stylesheet" href="default.css">
<style type="text/css">
@import url(header.css);
</style>
|
Порядок следования не влияет |
| Подключается три |
<link rel="stylesheet" href="default.css">
<style type="text/css">
@import url(header.css);
body
{
background:white url(MyWeb.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>
|
Подключается две внешних таблицы в дополнение к встроенной. Встроенные стили теоретически должны иметь выше приоритет, чем внешние. Но это зависит от конкретного Порядок следования не влияет |
| Подключается три |
<style type="text/css">
body
{
background:white url(MyWeb.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 rel="stylesheet" href="default.css">
|
Подключается две внешних таблицы в дополнение к встроенной. Встроенные стили теоретически должны иметь выше приоритет, чем внешние. Но это зависит от конкретного Порядок следования не влияет |
Чтобы проверить сказанное, выполните следующее (вручную, без Visual Studio 2005!)
Найдите в прилагаемом каталоге CSS файл embedded.htm и в этом же каталоге сделайте из него две копии с именами TestCSS.htm и ExternalCSS.css
Откройте в <head > встроенный стиль на строку подключения внешней CSS<link rel="stylesheet" href="ExternalCSS.css">
Откройте в
Откройте страницу
Опробуйте другие варианты подключения внешней CSS, приведенные ранее (если хотите!)Итак, внешняя CSS, это обычный текстовый файл, которому традиционно назначают расширение .css для лучшей узнаваемости, хотя может использоваться любое расширение. Мы убедились, что его можно создавать отдельно в любом
Создайте через Проводник Windows новый каталог с именем WebSite6
Откройте этот каталог через оболочку Visual Studio 2005 командой File/Open/Web Site
Выполните команду Website/Add New Item, выберите вариант Style Sheet и оставьте имя файла по умолчанию StyleSheet.css Оболочка добавит в проект новый файл
Наша главная задача, как программистов, - понимать и правильно
Не будем использовать созданную оболочкой заготовку StyleSheet.css, а научимся подключать свою
Откройте созданный нами ранее почти пустой проект WebSite6 (если не открыт)
Выполните команду Website/Add Existing Item. В появившемся диалоговом окне войдите в каталог CSS (мы в нем уже работали) и отметьте нужные файлы, удерживая при этом клавишу Ctrl
После щелчка на кнопке Add оболочка физически скопирует выделенные файлы в файл проекта WebSite6 и они появятся в панели Solution Explorer. Если вы не увидели там этих файлов, то щелкните на кнопке Refresh панели Solution Explorer, чтобы оболочка обновила представляемую после копирования информацию

Назначьте статическую страницу TestCSS.htm стартовой (команда Set As Start Page )и запустите ее на выполнение, чтобы убедиться, что и в оболочке она работает точно также, как и ранее в автономном режимеЕсли страница не содержит исполняемого ASP.NET -кода, то система ASP.NET ничего с ней не делает, а отсылает в неизменном виде клиенту. Если посмотреть на исходный
<html>
<head>
<title>Документ со встроенной CSS</title>
<meta content="text/html; charset=windows-1251" http-equiv="Content-Type">
<link rel="stylesheet" href="ExternalCSS.css">
</head>
<body>
<h1>
Заполните анкету!</h1>
<form>
<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>. Чтобы избавиться и от этого замечания редактора, нужно добавить атрибут
<form action=TestCSS.htm>
Посмотрите, как и в этом случае нам услужливо помогает подсказчик кода IntelliSense, предлагающий выбрать из списка файлов целевую страницу на сервере, которая будет принимать данные от формы

Вообще-то, большинство броузеров при пропущенном атрибуте полагают, что целевой будет та же самая страница. Но чтобы успокоить HTML редактор окончательно, укажем эту страницу явно.
Вызовите контекстное меню щелчком правой кнопки мыши на свободном месте верхней части каркаса оболочки и сбросьте флажок HTML Source Editing, чтобы закрыть одноименную панель настройки редактора
Удалите из заголовочного блока страницы код подключения внешней <link rel="stylesheet" href="ExternalCSS.css">
Переведите страницу в режим Design и посмотрите, какая она сразу стала блеклая (тусклая, бледная, невзрачная, некрасивая, ... - студент Леша Зиборов, продолжай! Только ты можешь дочитать до этого места!)
Вернитесь в режим Source и убедитесь, что оболочка добавила нужный
Опять удалите
Перейдите в режим Design, откройте панель Properties и через раскрывающийся список в ее верхней части выберите объект DOCUMENT
Найдите свойство
Очистите поле свойства StyleSheet, оболочка вновь удалит Таблицы CSS применяются не только к простым .
Откройте панель ToolboxМы видим, что доступной является только вкладка HTML, потому, что наша тестовая страница TestCSS.htm имеет расширение .htm.
Переименуйте в панели Solution Explorer тестовую страницу в TestCSS.aspx и сделайте ее же принимающей, исправив <form><form action=TestCSS.aspx runat="server">
Поместите на страницу из вкладки Standard текстовую метку Label и в панели Properties определитеCssClass=label Text=Стиль класса label
Откройте через Solution Explorer файл ExternalCSS.css и добавьте стилевое правило для класса label (рис ) Добавление нового стиля в класс label файла ExternalCSS.cssbody
{
background:white url(MyWeb.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;
}
.label
{
background-color:Green;
color:White;
font:bold;
font-size:x-large;
font-family:Courier New;
}
Выполните страницу, которая в 
Краткое знакомство с CSS и их поддержкой в Visual Studio 2005 закончили!
Применение CSS для стилевого оформления страниц ASP.NET имеет некоторые ограничения. Дело в том, что CSS являются решением стороны
Как и CSS, темы определяют набор стилей, которые называют оформлениями и которые можно применять на многих страницах ASP.NET. Особенности тем состоят в следующем:
Все темы помещаются в каталог с зарезервированным именем App_Themes, который можно добавить к приложению в панели Solution Explorer, выполнив команду Add ASP.NET Folder/Theme контекстного меню для узла приложения

Каждая тема должна храниться в своей одноименной папке и может состоять из нескольких файлов

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

Для темы можно все стилевые настройки элементов управления разместить в одном файле оформлений, а можно и в нескольких. Иногда просто удобнее группировать оформления по отдельным категориям элементов управления в соответствующих файлах. Для ASP.NET это не имеет никакого значения, поскольку она все равно считывает все файлы оформлений в каталоге темы как неделимое целое определения одной темы.
Проверим сказанное на практике:
Добавьте к проекту новую страницу TestTheme.aspx с раздельным кодом
Добавьте на страницу из вкладки Standard следующие элементы управленияBulletedListLabel CheckBox Button
Назначьте свойства
В панели Solution Explorer сделайте копию файла TestTheme.aspx и присвойте копии имя FirstSkin.aspx. Из него мы в дальнейшем сделаем файл оформлений
Удалите файл поддержки FirstSkin.aspx.cs
Настройте декларативно в панели Properties стилевые свойства объектов страницы FirstSkin.aspxBulletedList1:BackColor="Yellow"BorderColor="Red"BorderStyle ="Ridge "BorderWidth ="10px"BulletStyle="Numbered"ForeColor="Blue "Label1:BackColor="Blue "ForeColor="Yellow"ToolTip ="Текстовая метка"CheckBox1:BackColor="Red"BorderStyle ="Groove "Font -Bold ="True"ForeColor="White"Button :BackColor="#FFC0C0"BorderColor="Blue "BorderStyle ="Solid "BorderWidth ="2px"Font -Bold ="True"ForeColor="Blue "Внешний вид элементов управления после проведенных стилевых настроек должен быть таким

Перейдите в режим Source и удалите из файла FirstSkin.aspx весь код, кроме открывающих (рис ) Оставшийся код в файле 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
Создайте в приложении папку с зарезервированным именем
В панели Solution Explorer Тема подключается к странице с помощью атрибута @Page. Так, например, при применении темы с именем каталога MyTheme к нашей тестовой странице TestTheme.aspx
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="TestTheme.aspx.cs" Inherits="TestTheme"
Theme="MyTheme" %>
Тему можно подключить к странице и в панели Properties через свойство объекта DOCUMENT. В этом случае оболочка автоматически добавит атрибут к @Page с выбранным значением.
В раскрывающемся списке панели Properties для страницы TestTheme.aspx выделите объект DOCUMENT и установите свойство Theme ="MyTheme"
Назначьте страницу TestTheme.aspx стартовой и выполните ееДолжен получиться такой результат

Естественно, что переопределяются только те стилевые настройки элементов управления страницы, которые указаны в подключенной теме. Остальные настройки не переопределяются.
Вспомните, что в при подключении CSS стили начинают действовать на отображение элементов немедленно, на действие стилей мы увидим только на этапе выполнения. Механизм тем реализует стилевые настройки элементов управления, подключенные к форматируемой странице извне.
Но элементы управления страницы могут иметь свои индивидуальные стилевые настройки, которые мы им декларативно назначим при разработке страницы. В этом случае приоритет будут иметь одноименные настройки, указанные в подключаемой теме. Проверим это...
Измените в странице TestTheme.aspx атрибуты BackColor="Black " и ForeColor="Yellow" элемента CheckBox1, чтобы он имел черный фон и желтый текст
Выполните страницу и убедитесь, что элемент CheckBox1 будет иметь цвет фона красный, а Theme ="MyTheme"Объект DOCUMENT страницы имеет еще одно свойство StyleSheetTheme, к которому также можно подключить внешнюю тему. В этом случае приоритет будут иметь индивидуальные настройки элементов управления, которые в них были явно определены. Но те настройки по умолчанию, которые мы не определяли на странице, но которые содержатся в теме, действуют на свойства по умолчанию.

Любой вариант влияния темы на элемент управления можно отключить, если установить в этом элементе свойство EnableTheming="False".
Для страницы TestTheme.aspx в панели Properties выделите объект DOCUMENT, очистите поле его свойства StyleSheetTheme и подключите тему MyTheme к свойству Theme
Выделите объект CheckBox1 с индивидуальными настройками BackColor="Black "; ForeColor="Yellow" и установите для него EnableTheming="False"
Выполните тестовую страницу и убедитесь, что красивые настройки темы для этого элемента не действуют, а остались только настройки по умолчанию и индивидуальная настройка ![]() |
![]() |
Выделите объект CheckBox1 и верните для него EnableTheming="True"Стилевые настройки, которые мы до сих пор определяли в файле оформлений темы, являются настройками по умолчанию и применяются для всех элементов управления
Если просто определить в теме несколько вариантов настроек для одного и того же элемента управления, то ASP.NET выдаст ошибку об обнаружении неоднозначности. В этом случае в теме нужно применять именованные оформления с помощью атрибута SkinID. Тогда в странице наряду с общим подключением темы с помощью свойства можно будет определить значения SkinID именованных настроек элементов управления.
Значения SkinID в определениях темы должно быть уникальным только в группе однотипных элементов. Это значит, что мы можем создать несколько групп настроек разнотипных элементов с одинаковыми значениями атрибута SkinID и подключать из одной темы, по мере необходимости, к каждому элементу управления свои индивидуальные настройки.
Добавьте в страницу TestTheme.aspx элемент Table из вкладки HTML панели Toolbox. Таблицу расположите между кнопкой и Для нашего примера таблица должна иметь три столбца и пять строк. Оболочка не обладает развитыми средствами редактирования таблиц, поэтому проще настроить таблицу в режиме Source.
Поместите из вкладки Standard панели Toolbox в средний столбец таблицы пять серверных элементов Label , а в правый - пять серверных элементов CheckBox
Установите в добавленных объектах свойства в соответствии с контекстом таблицыSkinID не подключен: действуют общие настройки по умолчанию |
Label2 |
CheckBox2 |
Именованные настройки подключены: SkinID="Variant3" |
Label3 |
CheckBox3 |
Именованные настройки подключены: SkinID="Variant4" |
Label4 |
CheckBox4 |
SkinID="Variant5" подключен, но тема подавлена: EnableTheming="False" |
Label5 |
CheckBox5 |
Подключен несуществующий SkinID="XXX": настройки темы не действуют |
Label6 |
CheckBox6 |
Откройте файл оформлений FirstSkin.skin и дополните его индивидуальными настройками стилей, чтобы общий код его стал таким(рис ) Код файла оформлений FirstSkin.skin темы MyTheme<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" />
<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, то эти стилевые настройки никогда не будут применяться.
Сложные элементы управления включают в себя несколько разделов, требующих индивидуальных стилевых оформлений. Эти настройки могут занимать много места, если их использовать вместе с дескрипторным кодом страницы. Поэтому для таких элементов выносить громоздкий код стилевых настроек в отдельный файл оформлений очень даже удобно. Приведем пример с настройками элемента .
Создайте новую страницу со встроенным кодом поддержки и с именем TestCalendar.aspx
Назначьте страницу стартовой и поместите на нее из вкладки Standard элемент управления Calendar
Определите для объекта Calendar1 следующие стилевые настройки(рис ) Стилевые настройки объекта Calendar1 страницы TestCalendar.aspx<asp:Calendar ID="Calendar1" runat="server"
BackColor="white" ForeColor="black" BorderColor="black"
BorderStyle="solid" CellSpacing="1" Font-Names="Verdana"
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
Скопируйте из страницы TestCalendar.aspx в файл оформлений Calendar.skin весь дескрипторный код объекта Calendar1 вместе с его стилевыми настройками и удалите в копии атрибут ID="Calendar1"
Удалите в дескрипторном коде страницы TestCalendar.aspx код стилевых настроек объекта Calendar1, выделенный в приведенной выше таблице красным цветом, чтобы от объекта осталось только простое "мокрое место"<asp:Calendar ID="Calendar1" runat="server"> </asp:Calendar>
Через панель Properties выделите объект DOCUMENT и поключите к странице тему MyTheme в свойстве Theme
Выполните страницу и убедитесь, что вынесенный со страницы в тему большой блок стилевых настроек элемента Calendar работает также, как если бы он находился на самой страницеНиже приведены два варианта представления объекта Calendar1
![]() |
![]() |
С помощью с разными рисунками в зависимости от контекста применения. Пусть для кнопок OK будет использован один рисунок, а для кнопок Cancel - другой. Темы позволяют легко решить эту задачу.
В панели Solution Explorer через контекстное меню на папке MyTheme командой New Folder создайте подпапку ButtonImages для хранения рисунков кнопок
В панели Solution Explorer через контекстное меню на новой папке
Добавьте на страницу TestCalendar.aspx две картиночных кнопки ImageButton из вкладки Standard панели Toolbox и настройте через одноименные свойства в панели 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, чтобы добавить в тему новый файл оформления
Скопируйте настроенные ImageButton в файл Buttons.skin, предварительно очистив его от автоматически сгенерированных инструкций
Откорректируйте оформления в файле Buttons.skin, чтобы они выглядели так<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 в файле TestCalendar.aspx, чтобы от них осталось следующее<asp:ImageButton ID="ImageButton1" runat="server" SkinID="OKButton" /> <asp:ImageButton ID="ImageButton2" runat="server" SkinID="CancelButton" />
Исполните страницу Посмотрите, на странице находится дескрипторный код только создания сложных элементов управления, а большой код тонких настроек вынесен в файлы темы. Это очень удобно и для централизованного изменения стилевого оформления элементов управления, и для читабельности самой страницы.
Если у нас имеются хорошие наработки CSS, то ASP.NET позволяет использовать их для форматирования HTML-
Theme объекта DOCUMENT страницыCssClass элементов управления страницы<link>, используемого при традиционном способе подключения к странице, проследить, чтобы заголовочный <head runat="server"> ). В этом случае ASP.NET сама сгенерирует столько <link> в выходном Проверим это на примере. В панели Solution Explorer оболочки выполните следующие действия:
Скопируйте файл TestCSS.aspx и назначьте копии имя ThemeCSS.aspx и назначьте новую страницу стартовой
Скопируйте ThemeCSS.css
Переместите файл ThemeCSS.css в папку MyTheme проекта
Удерживая клавишу Ctrl, выделите файлы BackgroundImage.bmp и MyWeb.jpg в корне виртуального каталога и выполните для них команду Copy контекстного меню
Щелкните правой кнопкой мыши на узле MyTheme и выполните команду Paste, чтобы рисунки оказались в одном каталоге с таблицей ThemeCSS.css
Откройте страницу ThemeCSS.aspx на редактирование, удалите в ней <link> подключения внешней <head > является серверным
Исполните страницу и убедитесь, что стили пока не действуют, потому что не подключеныТеперь только осталось подключить тему MyTheme к странице.
В панели Properties выделите объект DOCUMENT и установите его свойство Theme в значение MyTheme
Выполните страницу ThemeCSS.aspx и убедитесь, что стили из внешней таблицы ThemeCSS.css работают
Назначьте страницу TestCSS.aspx, где мы CSS использовали напрямую, стартовой и выполните ееЧтобы сделать некоторые выводы, сравним полученные результаты, приведенные ниже в уменьшенном виде.
![]() |
![]() |
| Используется только |
Используется |
Выводы:
<link> ссылку на внешнюю CSS. Теперь осталось проверить тот факт, что ASP.NET подключает к странице все
В каталоге Theme сделайте еще три копии файла ThemeCSS.css с именем ThemeCSS1.css , ThemeCSS2.css , ThemeCSS3.css
Назначьте страницу ThemeCSS.aspx стартовой и выполните ее
На появившемся окне Исследуем блок кода заголовочного <. Он будет содержать такие строки
<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 автоматически вставляет в код столько
Удалите лишние файлы ThemeCSS1.css, ThemeCSS2.css и ThemeCSS3.css, чтобы они дальше не мельтешили у нас в глазахДо сих пор мы спокойно удаляли файл web.config приложения с уверенностью, что он будет вновь создан оболочкой. Тем более, что там содержалась только заготовка кода. Теперь пришла пора редактировать этот файл и удалять его уже будет жалко.
Ранее мы говорили, что при подключении к странице темы (в наших примерах - MyTheme ) через свойство объекта DOCUMENT оболочка автоматически вставляет соответствующий атрибут в @Page этой страницы, тем самым подключая к странице индивидуальную тему.
Например
<% @Page Language="C#" Theme="MyTheme" %>
Обычно проектировщики ратуют за одинаковое стилевое оформление страниц и используют в каждой из них одну и ту же тему. В этом случае удобнее будет не подключать каждую страницу к одной и той же теме, а указать общую тему в
Откройте страницы наших примеров, использующих темы, а именно: TestTheme.aspx, TestCalendar.aspx, ThemeCSS.aspx, и удалите в них из @Page атрибут Theme ="MyTheme"
Назначая каждую страницу стартовой, исполните их по очереди, чтобы убедиться, что отключенная тема в них не действует. Пока получилась грустная, унылая картина
Откройте на редактирование заготовку файла web.config, автоматически созданную оболочкой
Отредактируйте код файла web.config, добавив всего один <pages theme ="MyTheme" />, и сохраните изменения на дискеНиже приведен окончательный код файла web.config с указанием общей темы по умолчанию, в котором убраны громоздкие комментарии и пустые
<?xml version="1.0"?> <configuration> <system.web> <compilation debug="true"/> <authentication mode="Windows"/> <pages theme="MyTheme" /> </system.web> </configuration>
Назначая каждую из перечисленных выше страниц стартовой, вновь исполните их по очереди, чтобы убедиться, что тема опять заработала так, как будто-бы она была индивидуально подключена к каждой страницеЕсли нужно сделать так, чтобы общая тема действовала по умолчанию на множестве страниц, но не перезаписывала на них индивидуальные стилевые настройки элементов управления, то
<?xml version="1.0"?> <configuration> <system.web> <compilation debug="true"/> <authentication mode="Windows"/> <pages styleSheetTheme="MyTheme" /> </system.web> </configuration>
Если на какой-нибудь странице нужно сделать так, чтобы общая тема не действовала на нее по умолчанию, то есть два варианта:
@Page атрибут Theme ="Другая_тема"@Page страницы нужно вставить атрибут EnableTheming="false"<link> или в EnableTheming="false" отключает только skin -файлы, CSS все равно останется подключенной.Во всех наших примерах мы создавали активные страницы в корневом виртуальном каталоге сайта. Но для сайта с тысячами страниц это неприемлемый способ. Страницы могут группироваться (брыкаться, кусаться, кричать "Я пойду жаловаться в обком!") по любому признаку, например тематическому, и размещаться в отдельных папках развитой древовидной системы виртуальных каталогов. Корнем этого дерева должен быть виртуальный каталог сайта, его еще называют корнем Web-дерева.
В развитом Web-дереве применение общей темы по умолчанию является удобным способом стилизации страниц. В каждом каталоге можно разместить отдельный файл web.config со своей общей темой и все страницы этого каталога будут использовать эту тему по умолчанию.
До сих пор мы рассматривали случай, когда разработчик сам жестко привязывает тему к странице или группе страниц. Но иногда (для крутизны) может возникнуть необходимость поручить выбор темы для конкретной страницы пользователю с немедленным изменением ее стилевого оформления. При этом неважно, была ли включена на странице индивидуальная тема или по умолчанию применялась тема конфигурационного файла.
Все, что нужно сделать, это предусмотреть на странице интерфейс выбора темы, а в коде страницы динамически присвоить свойству Page. или Page.StyleSheetTheme выбранное пользователем значение. При этом важно понимать, что тема настраивается перед инициализацией страницы, поэтому соответствующий код нужно поместить в обработчик Page_PreInit(). Если это сделать позже, в обработчиках других событий, то попытка присвоить новое значение свойству Page. или Page.StyleSheetTheme вызовет ошибку компиляции.
С другой стороны, прочитать выбор пользователя можно только после создания страницы, когда присваивать свойству темы новое значение уже поздно. Поэтому динамическое задание темы нужно выполнять в два этапа:
Page_PreInit() назначить новую темуПри перезапуске страницы она должна быть переадресована на саму себя. Такую операцию можно выполнить либо методом , либо методом Server.. Первый метод реализует полный цикл с отправкой на Server.!
Рассмотрим все это на примере. Прежде всего, нужно создать несколько тем, чтобы было из чего пользователю выбирать.
В панели Sulution Explorer вызовите контекстное меню для папки MyTheme и выполните команду Copy
В панели Sulution Explorer вызовите контекстное меню для папки App_Themes, где должны храниться все темы приложения, и выполните на ней команду Paste два раза, чтобы создать еще две темы
Присвойте копиям такие замысловатые имена, какие давали нам в глубоком детстве на улице у родного батюшки, например, MyTheme1 и MyTheme2Обратите внимание, что новые темы имеют старое содержание, которое было бы желательно подправить, чтобы наглядно видеть влияние выбранной темы на оформление страницы. Мы это сделаем попозже и помягше - об чем должна болеть голова, прежде всего, у нашего дизайнера ( за што ему, акаянному, только деньги плотють ). Наше дело - режь, клей и запускай. Студент Зиборов! - и... чтобы еще работало!
Учитывая, что протокол HTTP не поддерживает сохранение состояний и что страница существует только на время обработки обратной отсылки, выбранную пользователем тему нужно где-то сохранять. Это могут быть cookie -наборы ( куки -файлы) на компьютере клиента, которые мы туда запишем без его ведома, если он забыл выключить их поддержку. Это могут быть ), которые мы будем пересылать туда-сюда. Это могут быть глобальные объекты уровня сеанса или приложения, которые существуют на сервере, пока не закончится сеанс с пользователем или не закроется ( на обед или профилактику ) приложение. Мы выбираем свободу, демократию и объект уровня сеанса !
Через панель Solution Explorer копируйте в корневой виртуальный каталог нашего сайта с примерами файл TestTheme.aspx и назовите его TestSwitchThemes.aspx
Определите новую страницу TestSwitchThemes.aspx стартовой
Откройте файл TestSwitchThemes.aspx на редактирование и добавьте в верхнюю часть страницы из вкладки Standard элемент пользовательского интерфейса для выбора темы, раскрывающийся список DropDownList
Переименуйте ID списка в lstSwitchThemes
Через панель Properties в режиме Events создайте для списка заготовку обработчика события SelectedIndexChanged, которое поступит на сервер с обратной отсылкой, если пользователь изменит выбор в списке
Добавьте на страницу перед списком серверный элемент Label с именем lblFirstLoadНа всякий пожарный случай (чтобы вам - его скопировать, а мне - отчитаться по объему текста перед зав. кафедрой Горенским Б.М.), приведу полный дескрипторный код, который будет иметь страница после проведения последних "оперативно-следственных" мероприятий
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="TestSwitchThemes.aspx.cs" Inherits="TestTheme" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Тест применения тем</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="lblFirstLoad" runat="server" Text="Label" />
<asp:DropDownList ID="lstSwitchThemes" runat="server"
OnSelectedIndexChanged="lstSwitchThemes_SelectedIndexChanged">
</asp:DropDownList>
<br />
<br />
<asp:BulletedList ID="BulletedList1" runat="server">
<asp:ListItem>Туризм</asp:ListItem>
<asp:ListItem>Спорт</asp:ListItem>
<asp:ListItem>Музыка</asp:ListItem>
<asp:ListItem>Танцы</asp:ListItem>
</asp:BulletedList>
<asp:Label ID="Label1" runat="server" Text="Текстовая метка" />
<asp:CheckBox ID="CheckBox1" runat="server" Text="Флажок"
BackColor="Black" ForeColor="Yellow" EnableTheming="True" />
<br />
<br />
<b>Тема подключена к странице через свойство Theme объекта DOCUMENT</b>
<br />
<table width="100%" border="1">
<tr>
<td>
SkinID не подключен: действуют общие настройки по умолчанию
</td>
<td>
<asp:Label ID="Label2" runat="server" Text="Label2" />
</td>
<td>
<asp:CheckBox ID="CheckBox2" runat="server" Text="CheckBox2" />
</td>
</tr>
<tr>
<td>
Именованные настройки подключены: SkinID="Variant3"
</td>
<td>
<asp:Label ID="Label3" runat="server" Text="Label3"
SkinID="Variant3" />
</td>
<td>
<asp:CheckBox ID="CheckBox3" runat="server"
Text="CheckBox3" SkinID="Variant3" />
</td>
</tr>
<tr>
<td>
Именованные настройки подключены: SkinID="Variant4"
</td>
<td>
<asp:Label ID="Label4" runat="server" Text="Label4"
SkinID="Variant4" />
</td>
<td>
<asp:CheckBox ID="CheckBox4" runat="server" Text="CheckBox4"
SkinID="Variant4" />
</td>
</tr>
<tr>
<td>
SkinID="Variant5" подключен, но тема подавлена: EnableTheming="False"
</td>
<td>
<asp:Label ID="Label5" runat="server" Text="Label5"
EnableTheming="False" SkinID="Variant5" />
</td>
<td>
<asp:CheckBox ID="CheckBox5" runat="server" Text="CheckBox5"
EnableTheming="False" SkinID="Variant5" />
</td>
</tr>
<tr>
<td>
Подключен несуществующий SkinID="XXX": настройки темы не действуют
</td>
<td>
<asp:Label ID="Label6" runat="server" Text="Label6"
SkinID="XXX" />
</td>
<td>
<asp:CheckBox ID="CheckBox6" runat="server" Text="CheckBox6"
SkinID="XXX" />
</td>
</tr>
</table>
<br />
<asp:Button ID="Button1" runat="server" Text="Отправить" />
</div>
</form>
</body>
</html>
Откройте на редактирование файл кода TestSwitchThemes.aspx.cs и заполните его такusing System;
//using System.Data;
//using System.Configuration;
//using System.Collections;
//using System.Web;
//using System.Web.Security;
//using System.Web.UI;
//using System.Web.UI.WebControls;
//using System.Web.UI.WebControls.WebParts;
//using System.Web.UI.HtmlControls;
public partial class TestTheme : 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);
}
}
Прежде, чем выполнить страницу, сделаем некоторые пояснения по приведенному C#-коду
DirectoryInfo мы явно указали с пространством имен System.IO и компилятор его увидитSession , Server, Response , Request являются общедоступными System.Web.UI.Page, который наследуется нашим классом TestTheme, а значит явно преобретает все эти свойстваSystem только потому, что в коде имеются ключевые слова string, int, bool, используемые при явном System.string, System.int, System.boolТеперь осталось внести какое-либо видимое различие в оформления тем, чтобы мы могли убедиться, что программно была подключена действительно другая тема. Для экономии своих сил внесем минимальные изменения, например, сделаем разными
Вызовите на редактирование файл App_Themes/MyTheme1/ThemeCSS.css и поменяйте в селекторе
Вызовите на редактирование файл App_Themes/MyTheme2/ThemeCSS.css и поменяйте в селекторе Наступил момент истины...
Исполните страницу и убедитесь в справедливости сказанного. Должен получиться такой уменьшенный результат![]() |
![]() |
![]() |
Подобным образом программно можно менять и другие стилевые свойства страницы и ее элементов, например, именованные оформления элементов управления, определенные атрибутом SkinID. Не обязательно давать пользователю возможность настройки стилевого оформления напрямую. Можно сделать оформление страниц и элементов косвенно зависимым от выбора пользователя. Принципиальной разницы с точки зрения кода здесь мало, главное - не переусердствовать!
И последнее... Все, что было сказано выше для декларативного способа подключения тем и приоритетов их применения, остается справедливым и для
Вот и закончилась тема про "темы"!
Очень часто требуется зафиксировать структуру страницы так, чтобы одни и те же элементы управления пользовательского интерфейса размещались в одном и том же месте как на одной странице, так и на множестве страниц сайта. Это позволяют сделать специальные страницы - шаблоны, которые существуют независимо, но подключаются к страницам по мере необходимости. Любая исполнимая страница может подключать только один из заранее заготовленных шаблонов.
Шаблон размечает
Перекомпоновка подключенного шаблона или его содержимого, а также подключение к исполнимой странице нового шаблона на
Исполнимая страница получает от используемого шаблона его

Шаблоны представляют собой обычные страницы, за исключением нескольких отличий:
@Page используется @Master System.Web.UI.MasterPage , вместо System.Web.UI.Page для обычной исполнимой страницыContentPlaceHolder используется для резервирования ContentPlaceHolder можно размещать в ячейках таблицы. При выполнении эти ячейки заполнятся Шаблон представляет собой полноценную страницу, готовую к выполнению, но не самостоятельно, а через исполнимую страницу содержимого. Оболочка имеет мастер для создания заготовок шаблонов, как и обычных страниц. Для примера, давайте создадим простую эталонную шаблон-страницу и пустую (вначале) исполнимую страницу, чтобы испытать шаблон.
Добавьте к проекту командой 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
Удалите ContentPlaceHolder и через контекстное меню редактора выполните команду Add Content Page (добавить страницу содержимого)
Оболочка сгенерирует такую заготовку файла Default.aspx
<%@ Page Language="C#"
MasterPageFile="~/FirstMasterPage.master"
AutoEventWireup="true" CodeFile="Default.aspx.cs"
Inherits="_Default" Title="Тестовая страница содержимого" %>
<%-- Add content controls here --%>
Пустой файл, - только @Page страницы со стандартными атрибутами страницы и атрибутом подключения шаблона.
<%--...--%> в дескрипторный код файлов ASP.NETОболочка прописала значение атрибута подключения MasterPageFile с путем относительно корня Web-дерева нашего сайта (ну, там наш шаблон и находится). Если уже подключенный к каким-то страницам шаблон переместить из корня в другую папку Web-дерева, то оболочка не меняет автоматически путь атрибута MasterPageFile во всех ссылающихся на шаблон страницах, это придется делать вручную (ох и работы, можно запутаться!). Поэтому нужно заранее спланировать, будем ли мы использовать
Создайте в панели Solution Explorer через контекстное меню для Web-корня подпапку MasterPages командой New Folder
Переместите мышью в папку MasterPages шаблон FirstMasterPage.master Теперь давайте откорректируем дескрипторный код исполнимой страницы.
В панели Solution Explorer дайте файлу Default.aspx новое имя FirstMasterPage.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, включенной нами ранее в
<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 текстовую строку, чтобы дескрипторный код стал таким(рис ) Дескрипторный код шаблона 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">
<h1>Привет студентам из "именованной области1" мастер-страницы!</h1>
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Перейдите в режим Теперь нужно настроить страницу содержимого, использующую шаблон.
Откройте на редактирование в режиме Source страницу содержимого FirstMasterPage.aspx, к которой подключен шаблон, и определите в контейнере <asp :Content > атрибуты ID самого ContentPlaceHolderID подключенного шаблона, на которую будет ссылаться Идентификатор ID самого контейнера < в странице содержимого определять необязательно, если только мы не планируем управлять им программно. Измененный код будет таким
<%@ 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>
Исполните страницу
Поместите на шаблон еще один контейнер шаблона ContentPlaceHolder и наполните его таким кодом(рис ) Дескрипторный код шаблона 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">
<h1>Привет студентам из "именованной области1" мастер-страницы!</h1>
</asp:ContentPlaceHolder>
<br />
<asp:ContentPlaceHolder ID="ContentPlaceHolder2" runat="server">
<h1>Привет студентам из "именованной области2" мастер-страницы!</h1>
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Перейдите на страницу содержимого Мы видим, что
Мы можем рассматривать итоговую страницу пользователя как двухслойную. На нижнем слое находится
Иными словами, именованная область шаблона спроецируется на итоговую страницу всегда: либо с содержимым (в том числе пустым) прикрепленного к ней контейнера, либо со своим содержимым (при его наличии), если для нее нет прикрепленного контейнера. О пустых полях внизу областей беспокоиться не нужно. На этапе выполнения они исчезнут. Просто, оболочка выделяет минимально необходимую
Обратите внимание на заголовки
Давайте добавим контейнер содержимого к нижней
На странице FirstMasterPage.aspx в режиме Design вызовите контекстное меню для нижней Оболочка добавит пустой контейнер содержимого и автоматически свяжет его в дескрипторном коде с именованной областью. Отсюда еще одна мораль:

После того, как на вновь созданной странице с содержимым проявятся
Если
Приведем более содержательный пример разработки страниц с использованием шаблонов. Учитывая, что HTML поддерживает только потоковую
В панели Solution Explorer вызовите контекстное меню для папки MasterPages, которую мы создали ранее, и выполните команду Add New Item
В окне мастера создания заготовок выберите шаблон Master Page и создайте эталонную страницу с именем Title .master без файла отделенного кода
Оболочка добавит заготовку эталонной страницы в каталог MasterPages, где ей и место.
Переведите в редакторе эталонную страницу Title.master в режим Design и удалите пока автоматически созданный экземпляр элемента ContentPlaceHolder (чтобы не путался под ногами)
В режиме Design из вкладки Standard панели Toolbox поместите в самом начале Image как контейнер для размещения ID="ImageBanner"Замечание. Элемент из вкладки HTML не будет проявляться на странице содержимого, потому что не обрабатывается сервером (если только ему не присвоить атрибут runat="server" )
Вызовите контекстное меню для папки MasterPages и выполните команду Add Existing Item. Найдите через открывшееся диалоговое окно файл Banner.png, который находится в прилагаемом к данной работе каталоге Pictures, и скопируйте его в папку MasterPages текущего сайта
Выделите экземпляр ImageBanner и присоедините к нему через свойство ImageUrl рисунок Banner.png из папки MasterPages Web-дерева сайта. Наш
Разместите после <h1 style="color: Green">
Мы приветствуем Вас на нашем сайте!!!
</h1>
Элемент шаблона ContentPlaceHolder по умолчанию растягивается по всей ширине страницы. Чтобы позиционировать его на

В трех ячейках таблицы будет размещаться потенциально заменяемое содержимое ContentPlaceHolder. В разных ячейках таблицы мы сделали разный фон только для учебных целей, чтобы сделать ячейки видимыми и показать, что фон ячеек таблицы с
Мы должны четко представлять, что элементы управления ContentPlaceHolder и являются прозрачными контейнерами для своего содержимого, если только мы искусстенно не создадим в них фон другими элементами, например, элементом , , Table. Поэтому, если мы на странице содержимого не создадим свой фон в замещающих элементах , то будет проявляться в итоговой странице фон элемента-контейнера
Поместите на Table
Используя боковые маркеры таблицы и команды меню Layout оболочки, постройте таблицу из трех строк и двух столбцов, чтобы она соответстворвала приведенному выше рисункуРекламация Большому Биллу: Мы конечно осознаем все революционные возможности Visual Studio 2005 по разработке программ. Но нас-то тоже нужно понять, мы привыкли к развитым
В конечном виде таблица вместе с вутренними стилями должна описываться следующими
<table border="0" width="100%">
<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 , к которому мы присоединим рисунок, задающий фон ячейки. ID=Panel1 копии этого элемента изменять не будем, поскольку не планируем в дальнейшем им программно управлять
Задайте для созданного экземпляра элемента управления Panel значения свойств: Width=100%; Height =100%, чтобы элемент полностью занял верхнюю ячейку таблицы
Через проводник Windows найдите в прилагаемом к данной работе каталоге Pictures файл BackTitleSrc.jpg и в любом Рисунок не должен быть слишком большим, чтобы "не застрял в проводах" по пути к пользователю.
В панели Solution Explorer в контекстном меню для папки MasterPages выполните команду Add Existing Item, найдите ваш рисунок BackTitle.jpg и скопируйте его в эту папку
Выделите на странице экземпляр Panel1 в верхней строке таблицы и через панель инструментов Properties присоедините в свойстве BackImageUrl этот рисунок, который многократным повторением займет всю Panel1Теперь можно разместить в ячейках таблицы прозрачные контейнеры-шаблоны элемента управления ContentPlaceHolder.
Поместите из вкладки Standard панели Toolbox в верхнюю строку таблицы в объект Panel1 элемент-контейнер ContentPlaceHolder, который будет представлять на странице ContentPlaceHolder1 для размещения
То же самое сделайте для правой_средней и нижней ячеек таблицы
В контейнер ContentPlaceHolder1 вставьте и отредактируйте такую строку<div style="font-weight: bold; font-size: xx-large; color: red; text-align: center">
Сведения об автошколе в целом
</div>
Вставьте в правый контейнер ContentPlaceHolder2 любой текст, например, такой или его частьВот уже более 12 лет мы занимаемся подготовкой водителей
категории "B" в г.Красноярске и всегда занимали первые места
в сводках МРЭО ГИБДД по качеству обучения. Автошкола всегда нацелена
на успех наших клиентов в сдаче экзаменов ГАИ с первого раза
и своевременном получении водительского удостоверения.
Мы обеспечиваем максимальные удобства своим клиентам. Для
этого существуют вечерняя, воскресная и заочная формы обучения.
Наши курсанты имеют возможность бесплатно и неограниченно пользоваться
компьютерным классом. Учебные автомобили прибывают по заявке
клиента к назначенному им месту. Развивается сеть филиалов автошколы
в г.Красноярске.
Наша компьютерная экзаменационная программа успешно используется
в ГИБДД г.Красноярска, Железногорска, Назарово, Емельяново, Шарыпово
для государственной аттестации кандидатов в водители. Мы неоднократно
выпускали цветные учебно-методические пособия по Правилам дорожного
движения, которыми постоянно пользуются большинство автошкол
города и края.
Лекционные занятия в автошколе ведут квалифицированные преподаватели
с учеными степенями и званиями с применением современных компьютерных
технологий. Комплексный подход к обучению и разнообразие форм
позволяют максимально сократить усилия наших клиентов и сроки
усвоения ими учебного материала. Парк учебных автомобилей насчитывает
более 15 штук, включая иномарки.
В нижний контейнер ContentPlaceHolder3, резервирующий место под <strong> Автошкола Диалог-Сервис в целом работает без перерыва на обед и выходных с 8 часов утра до 9 часов вечера!!! </strong>
Поместите в левую ячейку таблицы надпись, а из вкладки Standard панели Toolbox три HyperLink Дескрипторный код содержимого левой ячейки таблицы будет примерно таким
<td style="width: 25%; background-color: #9DFF7E" valign="top">
<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>
</td>
Сейчас мы пока не определяем в гиперссылках элементы
Все, таблицу мы заполнили. Попробуем разместить еще что-нибудь ниже таблицы, например, товарный знак и страшилку от воров интеллектуальной собственности! Хотя, мы сами ее воруем у других, будут воровать и у нас.
Отступите ниже таблицы одну-две строчки и добавьте из вкладки HTML панели Toolbox элемент управления Image . Щелкните на нем правой кнопкой мыши и выполните команду Run As Server Control, чтобы содержимое элемента проявилось в будущем на странице содержимого
В панели Solution Explorer вызовите контекстное меню для папки MasterPages и скопируйте в проект командой Add Existing Item из прилагаемого каталога Pictures рисунок 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 2007
</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>
Наступил момент истины! Пора тиражировать страницы содержимого на базе созданной
Мы для нашего примера создадим 4 страницы содержимого с простыми именами:
Satellites.aspx - первая страница, главная, не будет иметь свое содержимое, значит вся мастер страница проявится на выходе. Остальные три страницы будут переопределять все шаблоны Satellite1.aspx - будет вызываться по первой ссылке в разделе "Наши филиалы" и переопределять содержимое всех контейнеров, кроме Satellite2.aspx - будет вызываться по второй ссылке в разделе "Наши филиалы"Satellite3.aspx - будет вызываться по третьей ссылке в разделе "Наши филиалы"Есть несколько способов создания
В панели Solution Explorer выделите корень Web-дерева и выполните команду меню Website/Add New Item (или команду Add New Item контекстного меню)
В появившемся диалоговом окне отметьте показанные настройки, включая
В следующем окне выберите 
Созданная страница добавится в корень Web-дерева и будет содержать контейнеры с подключенным пустым содержимым для всех шаблонов выбранной
В панели Solution Explorer выделите нужную Будет создана страница содержимого, размещенная в том же каталоге, что и выделенная MasterPageFile будет прописан относительно корня Web-дерева, например,
MasterPageFile="~/ - (как-бы абсолютный адрес в пределах сайта)
Это значит, что мы можем переместить страницу содержимого в любую папку в пределах Web-дерева, и везде адрес
Откройте Обратите внимание, что двумя последними способами страница создается без отдельного файла поддержки C#. Это легко исправить, добавив к проекту файл .cs с предшествующим именем страницы. Правда, оболочка при этом спросит, создавать ли для этого класса отдельную папку со стандартным именем App_Code, на что нужно ответить Нет. И еще, при таком способе добавления к странице файла поддержки нужно вручную прописать необходимые атрибуты в декларации @Page
AutoEventWireup="true" CodeFile="XXX.aspx.cs" Inherits="YYY"
Вернемся к нашему примеру. Мы не собираемся программно управлять нашими страницами при иллюстрации рассматриваемой темы
Щелкните правой кнопкой мыши на открытой
Переименуйте страницу Default.aspx в Satellite .aspx и переместите ее в корневую папку Web-дерева
Подобным же образом создайте и переместите в корень остальные страницы содержимого: Satellite1.aspx, Satellite2.aspx, Satellite3.aspx. Но можно просто раскопировать в корне в трех экземплярах файл Satellite.aspx, учитывая, что все страницы будут ссылаться на одну и туже Теперь давайте корректировать заготовки страниц содержимого. Но прежде всего нужно доделать нашу
Выполните команду Window/Close All Documents, чтобы закрыть все редактируемые на текущий момент файлы
В панели Solution Explorer щелкните правой кнопкой мыши на файле ~/MasterPages/Title.master и выполните команду View Designer, чтобы открыть
Поочередно выделяя элементы гиперссылок, установите их свойство NavigateUrl на соответствующие страницы содержимого Satellite1.aspx, Satellite2.aspx, Satellite3.aspx. Сохраните и закройте Отредактируем страницы содержимого, начнем с Satellite.aspx
В панели Solution Explorer назначьте страницу Satellite.aspx стартовой и откройте ее на редактирование в режиме DesignЧто мы видим на данном этапе времени проектирования:
Удалите все контейнеры содержимого из страницы Satellite.aspx, оставьте только строку с @Page. Эта страница у нас будет стартовой и своего содержимого иметь не будет
Перейдите на странице Satellite.aspx в режим Design и мы видим, что проявилось и содержимое шаблонов
Исполните страницу
Пощелкайте по ссылкам и обратите внимание, как меняется адрес в Теперь нужно наполнить страницы ссылок индивидуальным содержимым.
Приведем окончательный вариант дескрипторного кода для всех страниц данного примера
ContentPlaceHolder должны находиться внутри <form></form>!<%@ Master Language="C#" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div style="text-align: center">
<asp:Image ID="ImageBanner" runat="server" ImageUrl="~/MasterPages/Banner.png" />
<h1 style="color: Green">
Мы приветствуем Вас на нашем сайте!!!
</h1>
<br />
<table border="0" width="100%">
<tr>
<td colspan="2">
<asp:Panel ID="Panel1" runat="server" Height="100%" Width="100%" BackImageUrl="~/MasterPages/BackTitle.jpg">
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
<div style="font-weight: bold; font-size: xx-large; color: red; text-align: center">
Сведения об автошколе в целом
</div>
</asp:ContentPlaceHolder>
</asp:Panel>
</td>
</tr>
<tr>
<td style="width: 25%; background-color: #9DFF7E" valign="top">
<strong style="color: Blue">Наши филиалы:</strong><br />
<br />
<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="~/Satellite1.aspx">Ленинский район</asp:HyperLink><br />
<br />
<asp:HyperLink ID="HyperLink2" runat="server" NavigateUrl="~/Satellite2.aspx">Центральный район</asp:HyperLink><br />
<br />
<asp:HyperLink ID="HyperLink3" runat="server" NavigateUrl="~/Satellite3.aspx">Свердловский район</asp:HyperLink>
</td>
<td style="background-color: #FFB8FF">
<asp:ContentPlaceHolder ID="ContentPlaceHolder2" runat="server">
Вот уже более 12 лет мы занимаемся подготовкой водителей категории "B" в г.Красноярске
и всегда занимали первые места в сводках МРЭО ГИБДД по качеству обучения. Автошкола
всегда нацелена на успех наших клиентов в сдаче экзаменов ГАИ с первого раза и своевременном
получении водительского удостоверения.
<br />
<br />
Мы обеспечиваем максимальные удобства своим клиентам. Для этого существуют вечерняя,
воскресная и заочная формы обучения. Наши курсанты имеют возможность бесплатно и
неограниченно пользоваться компьютерным классом. Учебные автомобили прибывают по
заявке клиента к назначенному им месту. Развивается сеть филиалов автошколы в г.Красноярске.
</asp:ContentPlaceHolder>
</td>
</tr>
<tr style="background-color: #FFFF92">
<td colspan="2">
<asp:ContentPlaceHolder ID="ContentPlaceHolder3" runat="server">
<strong>Автошкола Диалог-Сервис в целом работает без перерыва
на обед и выходных с 8 часов утра до 9 часов вечера!!!
</strong>
</asp:ContentPlaceHolder>
</td>
</tr>
</table>
<p style="text-align: right; color: Blue; font-family: 'Courier New'; font: bold italic">
<img id="IMG1" runat="server" src="LIGHT.ICO" />
ampnbsp;Copyright © 2007</p>
<asp:ContentPlaceHolder ID="ContentPlaceHolder4" runat="server">
<strong><em>Вы уж, пожалуйста, наведывайтесь к нам почаще!</em></strong>
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Все контейнеры < уничтожены, поэтому страница используется только как запускающая и не добавляет к
<%@ 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.Init Page.Init страницы содержимогоPage.Load Такой порядок означает, что если мы программно меняем одни и те же настройки в
< обычной страницы, где можно задавать все составляющие его <, добавив в @Page атрибут страницы содержимого. В этом случае <
Программно можно переопределять не только <, но и другие < < 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 переопределить <
<%@ Page Language="C#" MasterPageFile="~/MasterPages/Title.master"
Title="Untitled Page" %>
Замените атрибут Title @Page на следующий(рис ) Файл SatelliteExt.aspx<%@ Page Language="C#" MasterPageFile="~/MasterPages/Title.master"
Title="Декларативный заголовок SatelliteExt.aspx" %>
Исполните страницу - результат будет таким
Поскольку мы не создавали для страницы SatelliteExt.aspx отдельный файл кода поддержки, то код переопределения заголовка будем писать в скриптах страницы
Переведите страницу SatelliteExt.aspx в режим Design и щелкните дважды на притушенной области проступающего заполнителя Оболочка автоматически создаст блок скрипта и вставит в него заготовку обработчика события Page..
Заполните обработчик так(рис ) Файл SatelliteExt.aspx после добавления обработчика 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>
Исполните страницу - результат будет таким
Несмотря на то, что мы оставили декларативный атрибут , обработчик переопределил его в окончательном выводе. Это и понятно: декларативный атрибут инициируется при создании объекта заголовка, а обработчик 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 и будем обращаться к нему напрямую
(рис ) Добавление свойства доступа к дескриптору <h1> в файле Title.master<%@ 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 следующим кодом(рис ) Дополненный код страницы содержимого 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 и убедитесь, что @ MasterType указывает ASP.NET виртуальный путь к соответствующему файлу
Измените страницу содержимого SatelliteExt.aspx следующим образом(рис ) Измененный код страницы содержимого 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 и убедитесь, что Второй способ более предпочтительный, поскольку мы не вмешиваемся в код спроектированной
Иногда может возникнуть необходимость дать возможность пользователю подключать необходимые Page. в @Page. Теперь нам нужно программно менять атрибут Page.MasterPageFile.
Здесь нужно иметь ввиду следующее:
ContentPlaceHolderIDPage.PreInit страницы содержимого. Если это сделать в обработчиках более поздних событий, то будет сгенерировано исключениеVIEWSTATE ), глобальные объекты уровня сеанса или приложенияУчитывая, что наши страницы Satellite.aspx, Satellite1.aspx, Satellite2.aspx, Satellite3.aspx согласованы с Title.master, сделаем их копии и настроим под динамическую смену
Откройте ImageBanner (после открывающего <div> ) элемент ContentPlaceHolder с именем ContentPlaceHolderList. Сохраните и закройте файл Title.master
Сделайте копии соответствующих файлов и присвойте им имена Title1.master , SatelliteDynamic.aspx, SatelliteDynamic1.aspx, SatelliteDynamic2.aspx, SatelliteDynamic3.aspx
Определите страницу SatelliteDynamic.aspx стартовой
Откройте <script runat="server">...</script >ImageBanner и внесите еще какие-нибудь визуально отличимые измененияHyperLink еще одну с названием "Автошкола в целом"NavigateUrl гиперссылок значениями новых страниц содержимого
Откройте страницу содержимого SatelliteDynamic.aspx и в режиме Design создайте контейнер содержимого для шаблона ContentPlaceHolderList, выполнив на нем команду Create Custom Content контекстного меню
Добавьте в контейнер содержимого предваряющий текст "Выберите мастер-страницу :" и элемент DropDownList с именем lstMasterPages
Заполните раскрывающийся список
Items[0]Items[1]
Установите для списка lstMasterPages свойство AutoPostBack ="True"
В режиме Design Page_Load() и переименуйте его в Page_Init()
Скопируйте заготовку обработчика Page_Init() и переименуйте копию в Page_PreInit(), поскольку все они имеют одинаковую
В режиме Design lstMasterPages списка создайте обработчик изменения выбора опции lstMasterPages_SelectedIndexChanged()
Заполните обработчики так, чтобы окончательный код страницы был таким(рис ) Окончательный код страницы SatelliteDynamic.aspx<%@ Page Language="C#" MasterPageFile="~/MasterPages/Title.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 и добавьте в каждый из них после @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-дерева
Код страницы сделайте таким(рис ) Дескрипторный код страницы MasterPageLevel1.master<%@ Master Language="C#" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div style="text-align: center; color: #0000ff">
<h1>
Мастер-страница уровня Level1 - наибольшей глубины.
Ее можно использовать как верхний колонтитул
</h1>
<asp:ContentPlaceHolder ID="ContentPlaceHolderLevel1" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Теперь создайте MasterPageLevel0.master и подключите к ней предыдущую через атрибут MasterPageFile @Master Код страницы должен выглядеть так
<%@ Master Language="C#" MasterPageFile="~/MasterPageLevel1.master" %>
<asp:Content ID="ContentLevel0" ContentPlaceHolderID="ContentPlaceHolderLevel1" runat="server">
<table width="100%" 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>
Выполните для страницы MasterPageLevel0.master команду Website/Add Content Page, чтобы создать для нее страницу содержимого
Измените имя по умолчанию Default.aspx созданной страницы содержимого на TestMasterPageLevel.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 нельзя!
Для страниц, которые не имеют подключения MasterPageFile, можно задать
<configuration> <system.web> <pages masterPageFile="XXX.master" /> </system.web> </configuration>
Этот подход не считается надежным, поскольку требует строгого согласования всех страниц содержимого с шаблонами одной
Ну вот и приплыли, граждане студенты. До сих пор я писал изложение, а вы его читали. Теперь вы будете писать сочинение, а я его буду смотреть в аттестационную и зачетную недели! Отсюда вам мой наказ (читай "Указ!"):
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.