15.2 创建自己的主题

前文阐述了如何在ASP.NET中使用主题,但这里的主题是我们提供的一些现成的主题示例。同CSS一样,不是所需要的所有主题都能够从网上免费下载到,有时候,为了项目的需要,还需要自己来创建适合于项目的主题文件。

接下来,讨论如何在项目中根据需要创建自己的主题。

15.2.1 创建皮肤文件

皮肤文件((Sin)是主题的核心文件,它在ASP.NET页面上应用于服务器控件的样式定义。皮肤文件可以和CSS文件或图像一起使用。要创建用于ASP.NET应用程序的主题,可以在theme文件夹中使用一个皮肤文件,该文件可以是任意名称,但其文件扩展名必须是.skin。

为了能够更好地理解主题的概念,下面仍然以Calendar控件为例。如图15-7所示,首先需要在App_Themes文件夹下创建一个主题文件夹Red。之所以命名为Red,是因为在这里要创建一个Calendar控件的红色皮肤。

figure_0521_0406

图 15-7 项目结构图

创建好主题文件夹Red之后,需要在该文件夹里继续创建一个皮肤文件Default.skin。皮肤文件的创建方法为:用鼠标右击Red文件夹,选择“Add”|“New Item”命令,在弹出的“Add New Item”对话框里选择“Skin File”模板,在Name文本框里设置好皮肤文件的名称Default.skin,然后单击“Add”按钮就可以了。

或许这时候你会问,我们该如何编写皮肤文件呢?其实,与CSS文件相比,皮肤再简单不过了,它里面定义的就是ASP.NET控件里的属性。与ASP.NET普通Web页面上的常规服务器控件定义一样,这些控件定义也必须包含runat="server"属性。如果在皮肤文件中指定了某个控件的属性,那么就要在使用这个主题的Web页面上的服务器控件中包含该属性。

除此之外,还要注意在控件的皮肤文件没有指定ID属性。如果在这里指定了ID属性,当页面使用这个主题时就会出错。与此同时,在定义皮肤文件里定义控件时,如果需要对同一控件定义多个外观,SkinID属性也是必不可少的。Web页面上的服务器控件可以通过SkinID属性来调用皮肤文件相对应的控件。当然,如果只需要定义一个默认的控件属性,那么SkinID属性在这里就没必要定义了。代码清单15-2详细地展示了皮肤文件里Calendar控件的属性定义。

代码清单15-2 Default.skin


<asp:Calendar runat="server"

BackColor="White"BorderColor="#EFE6F7"

CellPadding="4"DayNameFormat="Shortest"Font-Size="0.8em"

ForeColor="Black"Height="180px"Width="200px">

<SelectedDayStyle BackColor="#8A170F"Font-Bold="True"

ForeColor="White"Font-Size="0.8em"/>

<SelectorStyle BackColor="#8A170F"Font-Size="0.8em"/>

<WeekendDayStyle BackColor="#E7E7E7"Font-Size="0.8em"/>

<OtherMonthDayStyle ForeColor="#8A170F"Font-Size="0.9em"/>

<TodayDayStyle BackColor="#F4000A"ForeColor="White"

Font-Size="0.8em"Font-Bold="True"/>

<NextPrevStyle VerticalAlign="Bottom"Font-Bold="True"

ForeColor="White"Font-Size="0.8em"/>

<DayHeaderStyle Font-Bold="True"Font-Size="0.8em"

BackColor="#F4000A"ForeColor="White"/>

<TitleStyle BackColor="#8A170F"BorderColor="Black"

Font-Bold="True"ForeColor="White"Font-Size="0.9em"/>

<DayStyle Font-Size="0.8em"/>

</asp:Calendar>


定义好Default.skin文件之后,就可以直接在页面里通过引用主题Red来使用该皮肤了,如代码清单15-3所示。

代码清单15-3 Test.aspx


<%@Page Language="C#"AutoEventWireup="true"

CodeBehind="Test.aspx.cs"Inherits="_15_2.Test"

Theme="Red"%>

<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

<title></title>

</head>

<body>

<form id="form1"runat="server">

<div>

<asp:Calendar ID="Calendar1"runat="server">

</asp:Calendar>

</div>

</form>

</body>

</html>


在代码清单15-3中,首先通过Page指令的Theme属性来引用主题Red。然后ASP.NET将会根据页面的Calendar控件自动引用上面定义的Default.skin文件里的Calendar控件定义。这样,页面的Cal endar控件将拥有Default.skin文件里的Calendar控件的相关属性定义。运行结果如图15-8所示。

figure_0522_0407

图 15-8 Test.aspx页面运行结果

15.2.2 在主题中包含CSS文件

除了在皮肤文件中定义的服务器控件属性之外,ASP.NET还允许把CSS用做主题的一部分。你可能会由于以下几个原因使用这一功能:

1)希望样式化那些不和服务器控件对应的HTML元素。

2)倾向于使用样式表,因为它们更加标准化,或者因为它们还可以同时用于格式化静态HTML页面。

3)已经为创建样式表付出了大量努力,不愿意创建主题去实现同样的格式化。

要在主题里使用CSS,首先必须把CSS放入主题文件夹。这里的CSS文件添加方法与添加普通的CSS文件方法一样。结果如图15-9所示。

figure_0523_0408

图 15-9 在主题里添加一个Default.css文件

创建好Default.css文件之后,就可以在该CSS文件里添加相关的样式代码。示例如代码清单15-4所示。

代码清单15-4 Default.css


body

{

font-family:Verdana;

font-size:small;

color:#000000;

margin:0;

padding:0;

margin-right:30;

text-align:left;

}

.title

{

text-transform:uppercase;

font-family:verdana;

font-size:30px;

font-weight:bold;

color:#8A170F;

}

hr{

border:0;

border-top:2px solid#8A170F;

height:2px;

}

h1

{

font-size:14px;

color:#DA2D26

}


在代码清单15-4中,分别创建了四个样式来供页面引用。样式引用方法与引用普通页面样式一样,唯一的区别就是不用在页面里使用<link>标签连接外部样式。因为ASP.NET会自动在这个主题文件夹里搜索所有的CSS文件,并把它们动态绑定到所有使用主题的页面。样式引用示例如代码清单15-5所示。

代码清单15-5 Test.aspx


<%@Page Language="C#"AutoEventWireup="true"

CodeBehind="Test.aspx.cs"Inherits="_15_2.Test"

Theme="Red"%>

<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

<title></title>

</head>

<body>

<form id="form1"runat="server">

<div>

<p class="title">

title样式测试

</p>

<h1>

h1样式测试

</h1>

<hr>

<asp:Calendar ID="Calendar1"

runat="server">

</asp:Calendar>

</div>

</form>

</body>

</html>


运行代码清单15-5,结果如图15-10所示。

figure_0524_0409

图 15-10 Test.aspx页面运行结果

如代码清单15-5所示,不用在页面代码里使用<link>标签连接外部样式,ASP.NET会自动在这个主题文件夹里搜索所有的CSS文件,并把它们动态绑定到所有使用主题的页面。因此,查看页面源代码时,会发现ASP.NET已经自动地把<link>标签添加到页面。如下面的代码所示:


<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<title>

</title>

<link href="App_Themes/Red/Default.css"type="text/css"

rel="stylesheet"/>

</head>

<body>

<form method="post"action="Test.aspx"id="form1">

<div class="aspNetHidden">

……


这样的方式应用CSS虽然简单明了,不过这种方式也有缺陷。为了把CSS绑定到页面,ASP.NET必须能够把<link>标签插入到Web页面的<head>节,而这仅在<head>标签具有“runat="server"”特性时才可能实现。也就是说,必须把<head>元素变成服务器端控件,ASP.NET才能自动插入CSS链接。加入这行代码后,只要设置页面的Theme属性就可以访问CSS规则了。

还需要说明的是,在主题里想使用多少CSS就可以使用多少CSS。ASP.NET会在<head>标签里自动加入多个<link>标签,各自对应主题里的一个CSS。

15.2.3 在主题中包含图像

除了CSS之外,还可以把图像作为主题的一部分从而重用它们。实际上,许多控件都使用图像创建更好的可视化外观,因此,把图像合并到统一使用主题的服务器控件中是完全有必要的。例如,假设设计了一幅图像,想把它用于整个网站的“确定”按钮。实现这一设计的第一步是把该图像加到主题文件夹。为了达到最好的组织效果,应该为存放图像创建一个或多个子文件夹,如图15-11所示。

figure_0525_0410

图 15-11 在主题文件夹里面添加图片

在主题文件夹中添加好图像之后,就可以在皮肤中使用该图像了。通常情况下,在皮肤文件中使用图像有如下两种方法:

1)把图像直接合并到皮肤文件中。这种方法主要应用于有图像属性的控件。方法很简单,只需要在皮肤文件里为控件的图像属性设置一张图像就可以了。如下面的代码所示:


<asp:ImageButton runat="server"

ImageUrl="Images/button.jpg"/>


设置好皮肤文件里的ImageButton控件之后,就可以在页面里调用了。调用方法如下面的代码所示:


<asp:ImageButton ID="ImageButton1"

runat="server"/>


在皮肤文件里添加对图片的引用时,一定要保证图片的URL是相对于主题文件夹而不是页面所在的文件夹。主题应用到控件时,ASP.NET自动在URL开始处插入Themes\ThemeName。

2)在CSS中定义图片,在皮肤文件中引用CSS。我们知道,并不是所有的服务器控件都提供了图像属性,用于直接使用主题文件夹中的图像。这时候,如果还需要为控件设置图像,那么就必须得先在CSS中定义图像,然后在皮肤文件中引用CSS。

下面的示例将演示以这种方式在主题中定义图像。先来创建一个CSS文件,如代码清单15-6所示:

代码清单15-6 Default.css


.calendar_title

{

background-image:url(Images/title.gif);

}

.calendar_selectedday

{

background-image:url(Images/selectedday.gif);

}


定义好CSS之后,就可以在皮肤文件中引用它们了。这里仍然以Calendar控件为例,可以在皮肤文件中通过Calendar控件的CssClass属性来调用这些样式,如代码清单15-7所示。

代码清单15-7 Default.skin


<asp:Calendar runat="server"

BackColor="White"BorderColor="#EFE6F7"

CellPadding="4"DayNameFormat="Shortest"Font-Size="0.8em"

ForeColor="Black"Height="180px"Width="200px">

<SelectedDayStyle BackColor="#8A170F"Font-Bold="True"

ForeColor="White"Font-Size="0.8em"

CssClass="calendar_selectedday"/>

<SelectorStyle BackColor="#8A170F"Font-Size="0.8em"/>

<WeekendDayStyle BackColor="#E7E7E7"Font-Size="0.8em"/>

<OtherMonthDayStyle ForeColor="#8A170F"Font-Size="0.9em"/>

<TodayDayStyle BackColor="#F4000A"ForeColor="White"

Font-Size="0.8em"Font-Bold="True"/>

<NextPrevStyle VerticalAlign="Bottom"Font-Bold="True"

ForeColor="White"Font-Size="0.8em"/>

<DayHeaderStyle Font-Bold="True"Font-Size="0.8em"

BackColor="#F4000A"ForeColor="White"/>

<TitleStyle BackColor="#8A170F"BorderColor="Black"

Font-Bold="True"ForeColor="White"Font-Size="0.9em"

CssClass="calendar_title"/>

<DayStyle Font-Size="0.8em"/>

</asp:Calendar>


如代码清单15-7所示,在皮肤文件((Dfault.skin)中的Calendar服务器控件里使用Default.css文件,并分别在Calendar控件的两个不同地方使用了CSS文件中指定的图像。首先,在<Selected DayStyle>元素中指定属性和值是CssClass="calendar_selectedday";其次,在<TitleStyle>元素中指定属性和值是CssClass="calendar_title"。这样,显示控件时,就会引用这些CSS类,并指向CSS文件中定义的图像。页面的调用方法如下面的代码所示:


<asp:Calendar ID="Calendar1"runat="server">

</asp:Calendar>


运行结果如图15-12所示。

figure_0526_0411

图 15-12 Test.aspx页面运行结果