Авторское право © WWW : Качественный хостинг сайтов и регистрация доменов
Перепубликация материалов,возможна только с устного или письменного разрешения Администрации сайта !
Название статьи , Опубликовано Документация » Статьи » Web-программирование » ASP.NET » Новое в asp.net 2 - темы и скины.
24 Май 2008 23:06

Используя функционал тем становится возможным контролировать внешний вид контролов сайта используя всего лишь несколько файлов – файлы шаблонов с расширением ".skin" и файлы с таблицами каскадных стилей (обычно имеют расширение ".css").Каждая папка в директории App_Themes считается отдельной темой. Вложение тем друг в друга не допускается. Каждая тема обычно состоит из одного или нескольких файлов скинов с расширением ".skin", а также других, необходимых для задания внешнего вида сайта файлов, таких как файлы каскадных таблиц стилей, картинок, xsl-преобразований и так далее, которые также могут быть упорядочены в подпапках корневой директории темы. Файлы скинов и таблиц стилей обычно расположены в корне темы, а картинки - в поддиректории images. Вы можете добавить столько файлов скинов контролов, сколько это необходимо. Обычно на один тип контрола создают один файл с шаблонами, но в общем случае, один ".skin"-файл может содержать множество разнородных элементов управления. Однако если в одном файле будут храниться атрибуты только одного и файл будет назван именем этого типа, то это позволит значительно упростить поиск нужного шаблона. Например, тема может включать в себя следующие файлы: Calendar.skin, Label.skin, Button.skin, TreeView.skin, GridView.skin и т.д. Каждый из этих файлов включает все скины, относящиеся к данному типу контрола. Скин контрола – это шаблон элемента управления с настройками свойств, определяющих внешний вид контрола, которые впоследствии будут использованы для визуального представления данного контрола.

В качестве примера рассмотрим создание скина для контрола "календарь". Создадим файл Calendar.skin со следующим содержимым:

<asp:Calendar runat="server" BackColor="White" 
               
BorderColor="#3366CC" BorderWidth="1px" CellPadding="1" 
               
DayNameFormat="Shortest" Font-Names="Verdana" Font-Size="8pt" 
               
ForeColor="#003399" Height="200px" Width="220px">
    <
SelectedDayStyle BackColor="#009999" Font-Bold="True" 
                     
ForeColor="#CCFF99" />
    <
SelectorStyle BackColor="#99CCCC" ForeColor="#336666" />
    <
WeekendDayStyle BackColor="#CCCCFF" />
    <
OtherMonthDayStyle ForeColor="#999999" />
    <
TodayDayStyle BackColor="#99CCCC" ForeColor="White" />
    <
NextPrevStyle Font-Size="8pt" ForeColor="#CCCCFF" />
    <
DayHeaderStyle BackColor="#99CCCC" ForeColor="#336666" Height="1px" />
    <
TitleStyle BackColor="#003399" BorderColor="#3366CC" BorderWidth="1px" 
               
Font-Bold="True"
               
Font-Size="10pt" ForeColor="#CCCCFF" Height="25px" />
  asp:Calendar>

Шаблон контрола выглядит как обычное задание серверного элемента управления в ASCX или ASPX файле за тем лишь исключением, что в нем не указывается параметр ID. Задание атрибута runat="server" обязательно! После сохранения этого файла в папке темы и задании данной темы в качестве текущей, все контролы типа Calendar на всех страницах сайта будут выводиться так как это задано в файле скина.

Следующий пример демонстрирует применение скина к контролу типа Label:

<asp:Label runat="server" ForeColor="Green" />

Мы можем поместить эту строку в новый файл Label.skin нашей темы и тогда все контролы типа Label на нашем сайте будут иметь одинаковый цвет текста.

Все скины делятся на два типа – скины по умолчанию и именованные скины. Скины не содержащие атрибута SkinID являются скинами по умолчанию и применяются ко всем контролам данного типа. Для каждого типа контрола может быть определен только один скин по умолчанию. Скин с установленным атрибутомSkinID называется именованным скином. Свойства именованного скина применяются только к контролам, имеющим такое же значение атрибута SkinID, что и у скина. При отсутствии в текущей теме подходящего для контрола именованного скина, применяются настройки из скина по умолчанию.

>В следующем примере для элемента управления ярлык определяется два скина – один это скин по умолчанию с цветом текста Green и второй скин для ярлыков с сообщениями об ошибках и прочих специфических нужд с цветом текста Red.

<asp:Label runat="server" ForeColor="Green" />
  <
asp:Label runat="server" ForeColor="Red" SkinID="Error" />

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

<body>
      <
form id="form1" runat="server">
      <
div>
          <
asp:Label runat="server" ID="label1" 
             
Text="Hello World" />
          <
br />
          <
asp:Label runat="server" ID="label2" 
             
Text="GoodBye World" SkinID="Error" />
      div>
      form>
  body>

С помощью скинов могут быть изменены практически все свойства контрола, имеющие отношение к его внешнему виду. Все атрибуты, разрешенные для установки в скинах должны быть помечены атрибутом System.Web.UI.ThemeableAttribute="true". Однако есть ряд свойств, задание которых в скине недопустимо. Например, такие свойства как ID и EnableViewState помечены как запрещенные к установке в файлах скинов. Также не допускаются к установке через скины такие атрибуты, как CommandName класса Button, AllowPaging, DataSource класса GridView и т.д. Делается это посредством установки атрибута ThemeableAttribute="false". Атрибут ThemeableAttribute может быть применен и к классу для обозначения поддержки данным контролом настройки своих параметров через скины. В качестве примера контрола не поддерживающего темы можно привести контрол Repeater, который наследует классу Control, помеченному атрибутом Themeable="false". Любой же контрол, наследующий классу WebControl, напротив, имеет этот атрибут установленный в "true" по умолчанию.

Области действия тем


По области действия различают темы локальные и темы, определенные глобально. Локальные темы хранятся в папке App_Themes приложения и могут использоваться только в данном приложении. Глобально-определенные темы должны быть расположены в папке %SystemRoot%Microsoft.NETFrameworkv2.0.xxxxxASP.NETClientFilesThemes. Данные темы может использовать любой сайт, работающий на данной машине. При совпадении названий локальной и глобальной темы к контролам будут применяться настройки из обоих тем, но приоритет будет у свойств локальной темы.
Установка текущей темы

Есть два способа указания страницам сайта, какую из имеющихся тем им использовать. От способа указания темы будет зависеть поведение выполняющей среды при работе с темами. Так если для этого будет использован атрибут Theme, то атрибуты из скинов темы будут иметь больший приоритет, чем атрибуты установленные у контролов непосредственно на странице. В случае же использования атрибута StylesheetTheme атрибуты заданные в теге контрола будут иметь больший приоритет при отрисовке контрола, чем атрибуты, полученные из скина.

Примечание: В режиме дизайнера страницы Visual Studio не отображает свойства контролов, заданные в скинах при установленном атрибуте Theme. Однако, если задавать тему через атрибут StyleSheetTheme, то в качестве побочного действия студийный дизайнер начинает их отображать, соответственно можно посмотреть все настройки в действии без компиляции сайта и просмотра его в браузере. Также, к сожалению, студийный редактор не поддерживает IntelliSense в ".skin"-файлах. Единственным способом удобного создания скинов является создание и настройка нужного элемента на странице и последующий перенос текста контрола в ".skin"-файл с удалением лишних атрибутов (таких как ID и EnableViewState).
Установка темы для отдельной страницы

В следующем примере показан способ указания текущей темы с использованием атрибута Theme директивы @Page.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" Theme="Синяя" %>
  DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
  <
html xmlns="http://www.w3.org/1999/xhtml">
  <
head runat="server">
   <
title>Темыtitle>
  head>
  <
body>
   <
form id="form1" runat="server">
    <
div>
     <
asp:Calendar ID="Calendar1" runat="server" />
     <
br /><asp:Label ID="Label1" runat="Server" Text="Theme" />
     <
br /><asp:Label ID="Label2" ForeColor="Brown" runat="Server" Txt="StyleSheetTheme" />
    div>
   form>
  body>
  html>

После этого, несмотря на то, что никаких настроек внешнего вида контролов на данной странице мы не делали, все контролы будет выглядеть так, как мы это задали в соответствующих файлах скинов текущей темы.

Если в данном примере заменить атрибут Theme на атрибут StylesheetTheme, то первая надпись будет выведена цветом темы, а вторая – коричневым цветом, заданным в теге контрола.

Установка темы для всего сайта


Используя файл настроек web.config, тему можно установить на уровне всего приложения (и даже на уровне целой машины, используя глобальный файл настроек machine.config). Для этого используются атрибуты theme и styleSheetTheme раздела .

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
      <
system.web>
         <
pages theme="Синяя" />
         <
authentication mode="Windows"/>
      system.web>
  configuration>

Установка темы для всей машины


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

Чтобы задать тему для всех сайтов, работающих на данной машине необходимо присвоить требуемое значение атрибуту theme раздела глобального файла настроек machine.config, который находится в папке %SystemRoot%Microsoft.NETFrameworkv2.0.xxxxxCONFIG. Если такого раздела нет, его следует создать. Например, он может выглядеть так:

<system.web>
  <
pages buffer="true" enableSessionState="true"
         
enableViewState="true" enableViewStateMac="true"
         
autoEventWireup="true" validateRequest="true"
         
enablePersonalization="false" theme="Синяя" />
  system.web>

При установке тем на уровне машины необходимо чтобы сами темы были также глобально определены, для дополнительной информации см. раздел "Области действия тем" данной статьи.

Примечание: Атрибуты Theme и StyleSheetTheme, определенные в директивах @Page страниц, будут переопределять значения одноименных атрибутов, заданных в конфигурационных файлах. А атрибуты, заданные в файле web.config будут иметь больший приоритет, нежели аналогичные глобальные настройки из файла machine.config.

Отключение тем


Ранее мы уже отметили, что при установке параметра Theme параметры из скина будут иметь больший приоритет, чем свойства контрола, определенные непосредственно в теге контрола на странице и будут переопределять их на этапе выполнения страницы. Однако это не всегда удобно и могут возникнуть ситуации, когда нам потребуется изменить такое поведение. Одним из способов решения этой задачи является отключение механизма тем для данного контрола. Делается это с помощью атрибута EnableTheming.

<asp:Label runat="server" ID="label1"
            
Text="Hello, from OdeToCode"
            
ForeColor="Green" EnableTheming="false" />

Необходимо отметить, что это свойство каскадно распространяется на все вложенные контролы. Таким образом, при установке атрибута EnableTheming="false" элементу управления Panel или пользовательскому контролу, все контролы, расположенные в данном контроле, также перестанут отображаться с использованием свойств из файлов скинов.

Аналогично можно отключить темы для отдельной страницы: <%@Page EnableTheming="False" %>. Данный атрибут отключает только использование атрибута theme, для того чтобы игнорировать все установки темы, в том числе и сделанные с использованием атрибута styleSheetTheme, потребуется конструкция следующего вида:

<%@ Page Theme="" StyleSheetTheme="" %>

Для отключения тем на уровне всего приложения потребуется сделать подобные установки уже в файле web.config:

<configuration>
          <
system.web>
                <
pages theme="" />
          system.web>
  configuration>

Соответственно для отключения тем на уровне всей машины придется править раздел файла machine.config.

Программная установка текущей темы


Помимо задания текущей темы в файле конфигурации или в теге страницы, возможна и программная установка темы в режиме выполнения. Установку темы следует производить до инициализации страницы, например в обработчике специального нового события PreInit. Поскольку скины темы применяются до события Init, их установка в нем уже бесполезна, даже более того, попытка сделать это приведет к исключению типа InvalidOperationException. Программная установка темы может быть полезна в том случае, если вы предоставляете пользователям возможность самим выбрать себе подходящую тему из списка предустановленных тем для сайта. Предпочтительную для пользователя тему можно хранить как одно из свойств его профиля и устанавливать ее для каждой просматриваемой страницы в обработчике события PreInit. Вот пример программной установки темы для страницы:

- файл класса для получения списка тем App_CodeDAL.cs:

public class DAL
 
{
      public
string[] GetThemes()
      {
         
// получаем список путей к подпапокам папки App_Themes
         
string[] folders = System.IO.Directory.GetDirectories(
             
System.Web.HttpContext.Current.Server.MapPath("~/App_Themes"));
         
// отрезаем от найденных полных путей только названия самих папок
         
for (int i = 0; i < folders.Length; i++)
          {
             
folders[i] = new System.IO.DirectoryInfo(folders[i]).Name;
          }
          return
folders;
   
//// Получение списка глобально-определенных тем
    //string[] globalThemes = Directory.GetDirectories(
    //    Path.GetDirectoryName(typeof(object).Assembly.Location)
    //    + "ASP.NETClientFilesThemes");
      
}
  }

- файл шаблона страницы с необходимыми контролами Default.aspx:

<%@ Page CodeFile="Default.aspx.cs" Inherits="_Default" %>
  <
html>
  <
head runat="server">
      <
title>Работаем с темамиtitle>
  head>
  <
body>
      <
form id="pageForm" runat="server">
          <
div>
              <
asp:DropDownList ID="ddlThemeSelector" runat="server" AutoPostBack="True" DataSourceID="odsDALGetThemes" />
              <
asp:ObjectDataSource ID="odsDALGetThemes" runat="server" SelectMethod="GetThemes" TypeName="DAL" />
          div>
      form>
  body>
  html>

- файл кода страницы Default.aspx.cs:

public partial class _Default : System.Web.UI.Page
 
{
      protected
override void OnPreInit(System.EventArgs e)
      {
          if (
IsPostBack && Request.Form[ddlThemeSelector.ClientID] != null)
          {
 
// Profile.Theme = Request.Form[ddlThemeSelector.ClientID];
             
Page.Theme = Request.Form[ddlThemeSelector.ClientID];
          }
      }
      protected
override void OnLoad(System.EventArgs e)
      {
         
// выделяем правильный элемент при первоначальной загрузке страницы
          // это необходимо для обозначения текущей темы, заданной статически
         
if (!IsPostBack)
          {
             
// заполним список данными из источника
             
ddlThemeSelector.DataBind();
             
// найдём запись текущей темы и пометим ее как выделенную
             
System.Web.UI.WebControls.ListItem li = ddlThemeSelector
                  
.Items.FindByText(Theme ?? StyleSheetTheme ?? "");
              if (
li != null)
              {
                  
li.Selected = true;
              }
          }
      }
  }

Обратите внимание, что в коде обработки события PreInit мы не можем напрямую обращаться к выделенному элементу списка ddlThemeSelector, а вынуждены искать его в параметрах пришедшей формы. Это следствие того, что на момент наступления события PreInit значения контролов на форме еще не инициализированы своими значениями.

Подобным образом можно установить значение свойства Theme страницы, для установки свойства StyleSheetTheme подобный подход не применим. Для программной установки значения свойства StyleSheetTheme необходимо переопределить его. В нашем случае, при выборе темы из списка, код получается такой:

public override String StyleSheetTheme
 
{
      
get 
      
{
          if (
Request.Form["ddlThemeSelector"] != null)
          {
              return
Request.Form["ddlThemeSelector"];
          }
          return
"Желтый";
      }
  }

Значение "ddlThemeSelector" получено из результирующего кода html: