A replacement of ASP.NET 2.0 theme&skin
.NET 2.0应该已经进入代码封装阶段了,不太可能有太大的变化了。ASP.NET 2.0 里提供的Theme/Skin解决方案,一方面过于繁复,而且有潜在的问题(具体参考另一篇Post: ASP.NET 2.0 Theme 的一个问题)。
一直在想一个简单稳定的替代方案,中秋节休息在家,想到了以下东东。
Theme/Skin大体可以分成三部分,布局、文字(包括字体和配色)和图片(包括动画)。
布局由Master页控制,可以继续用,网上已经有很多文章讨论如何动态改变Master页的办法。
文字和图片由网页中的一个属性Skin控制。不同的Skin存放在不同的目录结构中。
需要目录结构:
/Style 默认的Stylesheet目录
/Style/Skin1 对应与Skin1的Stylesheet目录
/Style/Skin2 对应与Skin2的Stylesheet目录
……
/Image 默认的图片目录
/Image/Skin1 对应与Skin1的图片目录
/Image/Skin2 对应与Skin2的图片目录
……
简单的步骤如下:
1、派生一个Page class,加入自己的属性 Skin,让所有的网页继承自这个Page class。
2、处理网页的Stylesheet,在Page class加入以下代码(根据Skin改写对应的Stylesheet文件的位置):
{
base.OnLoad(e);
if (this.Skin.Length > 0)
{
foreach (Control c in ((Control)this.Header).Controls)
{
if (typeof(HtmlLink).IsInstanceOfType(c))
{
HtmlLink hc = (HtmlLink)c;
if (hc.TagName.ToLower() == "link")
{
hc.Href = hc.Href.Substring(0, hc.Href.LastIndexOf("/") + 1) + this.Skin + "/" + hc.Href.Substring(hc.Href.LastIndexOf("/") + 1);
}
}
}
}
}
这样你的Stylesheet文件就可以自动根据指定的Skin变化了。
(如果需要的话,可以用同样的方法在WebControl级别再设一个Skin,这样你的WebControl(ascx)也可以有不同与Page的Skin,这种情况应该比较少,将有可能导致页面风格的不一致。)
3、处理图片,派生一个System.Web.UI.WebControls.Image class,加入如下代码(同上,改写Image对应的位置):
{
base.OnLoad(e);
System.Web.UI.Control c = this.NamingContainer;
while (c != null)
{
if (typeof(Skined.Page).IsInstanceOfType(c))
{
Skined.Page bp = (Skined.Page)c;
if (bp.Skin.Length > 0)
{
this.ImageUrl = this.ImageUrl.Substring(0, this.ImageUrl.LastIndexOf("/") + 1) + bp.Skin + "/" + this.ImageUrl.Substring(this.ImageUrl.LastIndexOf("/") + 1);
break;
}
}
c = c.NamingContainer;
}
}
同理,你的图片页会随着Skin自动转换了。
(其他Image对象的处理方法相同,比如ImageButton)
使用它们:
在设计网页的时候,可以完全抛开Skin部分,使用默认的目录中的Stylesheet和图片,例如:
在你的网页或者Master页里,使用:<link type="text/css" rel="stylesheet" href="Style/Default.css" />
如果你的网页指定了Skin1:
protected void Page_Load(object sender, EventArgs e)
{
this.Skin = "Test";
... ...
Render到客户端的将是:<link type="text/css" rel="stylesheet" href="Style/Skin1/Default.css" />
如果没有指定,将仍然Render出:<link type="text/css" rel="stylesheet" href="Style/Default.css" />
图片的使用:
<%@ Register TagPrefix="Skined" Namespace="Skined" %>
<Skined:Image ImageUrl="~/Image/calendar.gif" runat="server" />
同样的,如果你的网页指定了Skin1,Render到客户端的将是:<img src="Image/Skin1/calendar.gif">
几点说明:
1、这里只是一个构思和初步的代码,所有的代码都是未经优化的,如果直接使用的话,请自行处理,比如异常。
2、转载请注明出处
3、欢迎讨论
4、因为在国外有一段时间了,很多词汇不知道国内的翻法,只好直接用E文,上次自己乱翻,这次不敢了。