15.2 创建自己的主题
前文阐述了如何在ASP.NET中使用主题,但这里的主题是我们提供的一些现成的主题示例。同CSS一样,不是所需要的所有主题都能够从网上免费下载到,有时候,为了项目的需要,还需要自己来创建适合于项目的主题文件。
接下来,讨论如何在项目中根据需要创建自己的主题。
15.2.1 创建皮肤文件
皮肤文件((Sin)是主题的核心文件,它在ASP.NET页面上应用于服务器控件的样式定义。皮肤文件可以和CSS文件或图像一起使用。要创建用于ASP.NET应用程序的主题,可以在theme文件夹中使用一个皮肤文件,该文件可以是任意名称,但其文件扩展名必须是.skin。
为了能够更好地理解主题的概念,下面仍然以Calendar控件为例。如图15-7所示,首先需要在App_Themes文件夹下创建一个主题文件夹Red。之所以命名为Red,是因为在这里要创建一个Calendar控件的红色皮肤。
图 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所示。
图 15-8 Test.aspx页面运行结果
15.2.2 在主题中包含CSS文件
除了在皮肤文件中定义的服务器控件属性之外,ASP.NET还允许把CSS用做主题的一部分。你可能会由于以下几个原因使用这一功能:
1)希望样式化那些不和服务器控件对应的HTML元素。
2)倾向于使用样式表,因为它们更加标准化,或者因为它们还可以同时用于格式化静态HTML页面。
3)已经为创建样式表付出了大量努力,不愿意创建主题去实现同样的格式化。
要在主题里使用CSS,首先必须把CSS放入主题文件夹。这里的CSS文件添加方法与添加普通的CSS文件方法一样。结果如图15-9所示。
图 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所示。
图 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所示。
图 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所示。
图 15-12 Test.aspx页面运行结果