Theme and Skin
主题和控件外观:
ASP.NET2.0包含大量用于订制外观的新特性。其中,服务器端控件提供Style对象模型,用于订制字体、边界、背景前景颜色、宽度、高度等信息。同时,控件还支持使用CSS订制其外观。还可以把所有这些定制在Skin文件里,并把这些描述控件外观的Skin文件放置在Theme文件夹中反复使用。其中,通过将CSS定制到Style类中,并指定控件的Class属性来订制外观最为直接。而且在可视化界面的设计有相应的设计界面,不需要手动编写过多代码,在这里就不予说明。重点要介绍的是新的相对陌生的高级外观和主题设置。
1. MSDN中的概述:
主题是属性设置的集合,使用这些设置可以定义页面和控件的外观,然后在某个 Web 应用程中的所有页、整个 Web 应用程序或服务器上的所有 Web 应用程中一致地应用此外观。主题是属性设置的集合,使用这些设置可以定义页面和控件的外观,然后在某个 Web 应用程中的所有页、整个 Web 应用程序或服务器上的所有 Web 应用程中一致地应用此外观。
主题由一组元素组成:外观、级联样式表 (CSS)、图像和其他资源。主题将至少包含外观。主题是在网站或 Web 服务器上的特殊目录中定义的。
主题包括全局主题和页面主题:
全局主题是可以应用于服务器上的所有网站的主题。当您维护同一个服务器上的多个网站时,可以使用全局主题定义域的整体外观。服务器上的任何网站以及任何网站中的任何页面都可以引用全局主题。全局主题存在于“IIS默认根文件夹\aspnet_client\system_web\version\Themes”文件夹中。
页面主题是一个主题文件夹,其中包含控件外观、样式表、图形文件和其他资源,该文件夹是作为网站中的 ~\App_Themes 文件夹的子文件夹创建的。每个主题都是 \App_Themes 文件夹的一个不同的子文件夹。
主题 = 单个或者多个皮肤的组合。
外观文件(皮肤)具有文件扩展名 .skin,它包含各个控件(例如,、、 或 控件)的属性设置。控件外观设置类似于控件标记本身,但只包含您要作为主题的一部分来设置的属性。在 theme 文件夹中创建 .skin 文件。一个 .skin 文件可以包含一个或多个控件类型的一个或多个控件外观。可以为每个控件在单独的文件中定义外观,也可以在一个文件中定义所有主题的外观。
皮肤 = 控件的可视属性。
有两种类型的控件外观 -“默认外观”和“已命名外观”:
-
当向页应用主题时,默认外观自动应用于同一类型的所有控件。如果控件外观没有 SkinID 属性,则是默认外观。例如,如果为 Calendar 控件创建一个默认外观,则该控件外观适用于使用本主题的页面上的所有 Calendar 控件。(默认外观严格按控件类型来匹配,因此 Button 控件外观适用于所有 Button 控件,但不适用于 控件或从 Button 对象派生的控件。)
-
已命名外观是设置了 属性的控件外观。已命名外观不会自动按类型应用于控件。而应当通过设置控件的 SkinID 属性将已命名外观显式应用于控件。通过创建已命名外观,可以为应用程序中同一控件的不同实例设置不同的外观。
2. 主题的好处:
(1) 未使用Theme:结构复杂,格式混乱,不易于修改和阅读。
未使用skin文件的aspx页面:
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="WithoutTheme.aspx.vb" Inherits="WithoutTheme" %>
<!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 id="Head1" runat="server">
<title>Page with Example Theme Applied</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h3>
Page with Example Theme Applied</h3>
<asp:Label ID="Label1" Font-Bold="true" ForeColor="orange" runat="server" Text="Hello 1" /><br />
<asp:Label ID="Label2" Font-Bold="true" ForeColor="orange" runat="server" Text="Hello 2" /><br />
<asp:Label ID="Label3" Font-Bold="true" ForeColor="orange" runat="server" Text="Hello 3" /><br />
<br />
This is some example text: The quick brown fox jumped over the lazy dog.<br />
<br />
<asp:Calendar ID="Calendar1" runat="server"
BackColor="White" BorderColor="Black" BorderStyle="Solid" CellSpacing="1"
Font-Names="Verdana" Font-Size="9pt" ForeColor="Black" Height="250px"
NextPrevFormat="ShortMonth" Width="330px" >
<SelectedDayStyle BackColor="#333399" ForeColor="White" />
<OtherMonthDayStyle ForeColor="#999999" />
<TodayDayStyle BackColor="#999999" ForeColor="White" />
<DayStyle BackColor="#CCCCCC" />
<NextPrevStyle Font-Bold="True" Font-Size="8pt" ForeColor="White" />
<DayHeaderStyle Font-Bold="True" Font-Size="8pt" ForeColor="#333333" Height="8pt" />
<TitleStyle BackColor="#333399" BorderStyle="Solid" Font-Bold="True" Font-Size="12pt"
ForeColor="White" Height="12pt" />
</asp:Calendar>
<br />
<asp:GridView ID="GridView1" AutoGenerateColumns="False" DataSourceID="SqlDataSource1"
DataKeyNames="au_id" runat="server" CellPadding="4"
ForeColor="#333333" GridLines="None" Width="461px" >
<FooterStyle BackColor="#1C5E55" Font-Bold="True" ForeColor="White" />
<RowStyle BackColor="#E3EAEB" />
<PagerStyle BackColor="#666666" ForeColor="White" HorizontalAlign="Center" />
<SelectedRowStyle BackColor="#C5BBAF" Font-Bold="True" ForeColor="#333333" />
<HeaderStyle BackColor="#1C5E55" Font-Bold="True" ForeColor="White" />
<EditRowStyle BackColor="#7C6F57" />
<AlternatingRowStyle BackColor="White" />
<Columns>
<asp:BoundField DataField="au_id" HeaderText="au_id" ReadOnly="True" SortExpression="au_id" />
<asp:BoundField DataField="au_lname" HeaderText="au_lname" SortExpression="au_lname" />
<asp:BoundField DataField="au_fname" HeaderText="au_fname" SortExpression="au_fname" />
<asp:BoundField DataField="state" HeaderText="state" SortExpression="state" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ConnectionString="<%$ ConnectionStrings:pubsConnectionString %>" ID="SqlDataSource1"
runat="server" SelectCommand="SELECT [au_id], [au_lname], [au_fname], [state] FROM [authors]">
</asp:SqlDataSource>
</div>
</form>
</body>
</html>
使用独立skin文件保存样式信息的同一aspx页面:
<%@ Page Language="VB" Theme="Theme1" %>
<!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 id="Head1" runat="server">
<title>Page with Example Theme Applied</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h3>
Page with Example Theme Applied</h3>
<asp:Label ID="Label1" runat="server" Text="Hello 1" /><br />
<asp:Label ID="Label2" runat="server" Text="Hello 2" /><br />
<asp:Label ID="Label3" runat="server" Text="Hello 3" /><br />
<br />
This is some example text: The quick brown fox jumped over the lazy dog.<br />
<br />
<asp:Calendar ID="Calendar1" runat="server"/>
<br />
<asp:GridView ID="GridView1" AutoGenerateColumns="False" DataSourceID="SqlDataSource1"
DataKeyNames="au_id" runat="server">
<Columns>
<asp:BoundField DataField="au_id" HeaderText="au_id" ReadOnly="True" SortExpression="au_id" />
<asp:BoundField DataField="au_lname" HeaderText="au_lname" SortExpression="au_lname" />
<asp:BoundField DataField="au_fname" HeaderText="au_fname" SortExpression="au_fname" />
<asp:BoundField DataField="state" HeaderText="state" SortExpression="state" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ConnectionString="<%$ ConnectionStrings:pubsConnectionString %>" ID="SqlDataSource1"
runat="server" SelectCommand="SELECT [au_id], [au_lname], [au_fname], [state] FROM [authors]">
</asp:SqlDataSource>
</div>
</form>
</body>
</html>
注意: 由于在Html中去掉了外观属性的设置,所以在设计时不会看到在skin文件中设置的外观效果。只有在运行时呈现。
3. 如何:在页面中应用主题:
首先:在网站项目上点右键,选择“添加ASP.NET文件夹”,选择“主题”。在解决方案资源管理器中的App_Theme文件夹中就会生成相应的Theme子文件夹。
其次:向新文件夹中添加组成主题的外观、样式表和图像文件都可以。在新建的Theme文件夹上点击右键,选择“添加项”,选择“外观文件”,并对其重命名。在新建的 .skin 文件中,添加常规控件定义(使用声明性语法),但仅包含要为主题设置的属性 (Property) 且不包括 ID 属性 (Attribute)。控件定义必须包含
runat="server"
属性。
注意: 典型约定是为每个控件创建一个 .skin 文件,如 Button.skin 或 Calendar.skin。不过,您可以根据自己的需要创建或多或少的 .skin 文件;外观文件可包含多个外观定义。
例如:将上面介绍的两个页面的Html代码中差异的部分,即对控件外观属性的描述的代码取出放到我们新建的Skin文件夹中,如下所示,分别对Label、Calendar、GridView控件的外观进行了描述。
<asp:Label runat="server" Font-Bold="true" ForeColor="orange"/>
<asp:Calendar runat="server" BackColor="White" BorderColor="Black" BorderStyle="Solid" CellSpacing="1"
Font-Names="Verdana" Font-Size="9pt" ForeColor="Black" Height="250px"
NextPrevFormat="ShortMonth" Width="330px" >
<SelectedDayStyle BackColor="#333399" ForeColor="White" />
<OtherMonthDayStyle ForeColor="#999999" />
<TodayDayStyle BackColor="#999999" ForeColor="White" />
<DayStyle BackColor="#CCCCCC" />
<NextPrevStyle Font-Bold="True" Font-Size="8pt" ForeColor="White" />
<DayHeaderStyle Font-Bold="True" Font-Size="8pt" ForeColor="#333333" Height="8pt" />
<TitleStyle BackColor="#333399" BorderStyle="Solid" Font-Bold="True" Font-Size="12pt"
ForeColor="White" Height="12pt" />
</asp:Calendar>
<asp:GridView runat="server" CellPadding="4"
ForeColor="#333333" GridLines="None" Width="461px" >
<FooterStyle BackColor="#1C5E55" Font-Bold="True" ForeColor="White" />
<RowStyle BackColor="#E3EAEB" />
<PagerStyle BackColor="#666666" ForeColor="White" HorizontalAlign="Center" />
<SelectedRowStyle BackColor="#C5BBAF" Font-Bold="True" ForeColor="#333333" />
<HeaderStyle BackColor="#1C5E55" Font-Bold="True" ForeColor="White" />
<EditRowStyle BackColor="#7C6F57" />
<AlternatingRowStyle BackColor="White" />
</asp:GridView>
创建外观的一个方便途径是将控件添加到页中,然后对其进行配置以使其具有所需外观。例如,可将 控件添加到页中并设置其日标头、所选日期和其他属性。然后,可以将控件定义从页复制到外观文件,然后移除 ID 属性。
在同一skin文件中,可以存在同一种控件的不同配色方案。那么不同的配色方案之间如何区分,又如何在页面中分别加载呢?就是通过制定每种配色方案的SkinID属性。
例如:以下代码出自一个按照“典型约定”,专为Label控件创建的Skin文件。其中包含一个默认配色方案(无SkinID属性的声明)和一个可选配色方案(有SkinID属性的配色方案)。
<asp:label runat="server" font-bold="true" forecolor="orange" />
<asp:label runat="server" SkinID="Blue" font-bold="true" forecolor="blue" />
注意: 不管在当前Skin文件中还是在包含该Skin文件的Theme文件夹下的其它Skin文件中都不能再次出现无SkinID属性的Label配色方案说明。否则将出现冲突。也就是说只能存在该控件的一种默认配色方案!
最后:定义主题之后,可以使用 指令的 Theme 或 StyleSheetTheme 属性将该主题放置在单个页上,或者可以通过设置应用程序配置文件中的 元素将其应用于应用程序中的所有页。如果在 Machine.config 文件中定义了 元素,则主题将应用于服务器上的 Web 应用程序中的所有页。
如果设置了页的 属性,则主题和页中的控件设置将进行合并,以构成控件的最终设置。如果同时在控件和主题中定义了控件设置,则主题中的控件设置将重写控件上的任何页设置。即使页面上的控件已经具有各自的属性设置,此策略也可以使主题在不同的页面上产生一致的外观。
例如:
<%@ Page Language="VB" Theme="Theme2" %>
例如:
<%@ Page Language="VB" StyleSheetTheme="Theme2" %>
例如:BasicBlue为已定义好的主题文件夹(Theme文件夹)
<configuration>
<system.web>
<pages theme="BasicBlue" />
</system.web>
</configuration>
<asp:Label ID="Label1" runat="server" Text="Hello 1" /><br />
<asp:Label ID="Label2" runat="server" Text="Hello 2" ForeColor="blue" />
<asp:Label ID="Label3" runat="server" SkinID="Blue"/><br />
3. 如何:在页面中编码动态更改主题:
下面是一个小例子:
首先:我们要在App_Themes文件夹中定义两套不同的主题,即建立两个Theme文件夹。在其中分别加入一个Skin文件,和一个简单样式表文件(.css)。
例如:在Theme1主题包(文件夹)中加入Skin1.skin和StyleSheet1.css,分别编码如下:
Skin1.skin:
<asp:Label runat="server" Font-Bold="true" ForeColor="orange"/>
<asp:Calendar runat="server" BackColor="White" BorderColor="Black" BorderStyle="Solid" CellSpacing="1"
Font-Names="Verdana" Font-Size="9pt" ForeColor="Black" Height="250px"
NextPrevFormat="ShortMonth" Width="330px" >
<SelectedDayStyle BackColor="#333399" ForeColor="White" />
<OtherMonthDayStyle ForeColor="#999999" />
<TodayDayStyle BackColor="#999999" ForeColor="White" />
<DayStyle BackColor="#CCCCCC" />
<NextPrevStyle Font-Bold="True" Font-Size="8pt" ForeColor="White" />
<DayHeaderStyle Font-Bold="True" Font-Size="8pt" ForeColor="#333333" Height="8pt" />
<TitleStyle BackColor="#333399" BorderStyle="Solid" Font-Bold="True" Font-Size="12pt"
ForeColor="White" Height="12pt" />
</asp:Calendar>
{} {
background-color:Silver;
}
Skin2.skin:
< asp:Calendar runat ="server" BackColor ="White" BorderColor ="Black" BorderStyle ="Solid" CellSpacing ="1"
Font-Names ="Verdana" Font-Size ="9pt" ForeColor ="Black" Height ="250px"
NextPrevFormat ="ShortMonth" Width ="330px" >
< SelectedDayStyle BackColor ="#333399" ForeColor ="White" />
< OtherMonthDayStyle ForeColor ="#999999" />
< TodayDayStyle BackColor ="#999999" ForeColor ="White" />
< DayStyle BackColor ="#CCCCCC" />
< NextPrevStyle Font-Bold ="True" Font-Size ="8pt" ForeColor ="White" />
< DayHeaderStyle Font-Bold ="True" Font-Size ="8pt" ForeColor ="#CCCCCC" Height ="8pt" />
< TitleStyle BackColor ="#333399" BorderStyle ="Solid" Font-Bold ="True" Font-Size ="12pt"
ForeColor ="White" Height ="12pt" />
</ asp:Calendar >
body
{}{
background-color:Gray;
}
注意: 在上面两个处于不同主题包的Skin文件中,同时定义了Label控件的默认配色方案,但是没发生冲突。可见,默认配色方案和SkinID的限制只局限于单个主题包内部。
加载这两个主题的网页文件就很简单了,仅仅需要加载一个Label控件和一个Calender控件而已。那么如何实现在两种主题的切换呢?我们看看网页后端的代码隐藏文件:
static int i = 0;
protected void Page_PreInit()
{
i++;
if (i % 2 == 0)
{
Page.Theme = "Theme2";
Label1.Text = "主题2";
}
else
{
Page.Theme = "Theme1";
Label1.Text = "主题1";
}
}
至此,该小实例就完成了。在网页中浏览,点击刷新即可观察到主题的变化。
4. 如何:定义Theme模板:
Theme模板也是一个Skin文件,它不单包含控件的显示模式,还包含许多控件的摆放模式即控件的组合。
对一些组合控件,自定义控件我们可以通过Theme模板订制它们的摆放模式。
例如:ASP.NET2.0中的新控件:Login控件,我们可以更改其显示样式。Skin文件定义如下:
<asp:Login runat="server">
<LayoutTemplate>
<i>Please log in to this site:</i><br /><br />
<table border="0" cellpadding="10" bgcolor="beige">
<tr>
<td>
<asp:Label Font-Bold="true" AssociatedControlID="UserName" ID="UserNameLabel" runat="server">User Name:</asp:Label>
<br />
<asp:TextBox ID="UserName" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ControlToValidate="UserName" ErrorMessage="User Name is required."
ID="UserNameRequired" runat="server" ToolTip="User Name is required." ValidationGroup="Login1">*</asp:RequiredFieldValidator>
</tr>
<tr>
<td>
<asp:Label Font-Bold="true" AssociatedControlID="Password" ID="PasswordLabel" runat="server">Password:</asp:Label>
<br />
<asp:TextBox ID="Password" runat="server" TextMode="Password"></asp:TextBox>
<asp:RequiredFieldValidator ControlToValidate="Password" ErrorMessage="Password is required."
ID="PasswordRequired" runat="server" ToolTip="Password is required." ValidationGroup="Login1">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td>
<asp:Button CommandName="Login" ID="LoginButton" runat="server" Text="Log In" ValidationGroup="Login1" />
</td>
</tr>
</table>
<br />
<asp:Literal EnableViewState="False" ID="FailureText" runat="server"></asp:Literal>
</LayoutTemplate>
</asp:Login>
加载该方案后,我们可以与未加载方案的Login控件对比一下。
至此,关于Theme和Skin的相关知识就介绍完了,在编程中可能会遇到更多的需求和问题,需要不断学习。
祝大家编程愉快!