styleTemplates是风格设置的根节点,default是默认的风格名称;masterRoot是指模板页的根目录的地址;style结点是各个风格的名称,以及其所使用的主题的名称;style结点下的masterPages结点组包含此风格所使用的模板的信息;其中Page子结点对应每个独立的页面,path属性记录的是页面的路径,master属性是每个页面对应的模板的路径。
page结点的master属性没有给出模板的全路径,这么做一个是为了使目录结构更一目了然,还有就是不想master属性的内容变得很长,所以需要在程序中指定页面的模板的路径为 masterRoot + Theme + masterPage名称。这样在模板的根目录下,必须建立与主题同名的目录,然后将模板位于该目录下。
在创建页面时,我们需要要选择一个模板。注意到这一点非常重要,因为这个模板实际上是该页面的默认模板。当我们在Web.config中将相应风格的page结点留空时(没有对此页面设置模板),那么就会应用这个模板。所以在Web.Config中定义风格的模板,只是覆盖了这个我们在创建页面时选择的模板。由此,我们只用定义一套完整的Master Page模板页,供每个页面在创建时选择。而Web.config风格结点下设置的master page,实际上仅仅是动态地覆盖这些模板。
以上面的配置为例:当我们将 “春意盎然” 下的第二个 page 结点注释掉时,它会应用创建页面时所选择的模板。“默认风格”下面没有设置任何的 page 结点,所以对于该风格的每个页面,都会应用创建页面时所选择的模板。
如果你希望仅使用Css来换肤,你可以使用也可以不使用Master Page,那么在Web.Config中可以像下面这样设置:
<styleTemplates default="默认风格" masterRoot="">
<style theme="Default" ></style>
<style theme="Spring" ></style>
<style theme="Autumn" ></style>
</styleTemplates>
对于上面使用Master Page时的设置,站点的目录结构如下所示:
可以看到模板页的根目录下包含了目录Default、Spring与主题名称相同(必须)。之后我们要编写结点处理程序,如何编写自定义结点处理程序,我在《.Net 自定义应用程序配置》一文中已经详细的讨论了,所以这里我们直接看实现,在AppCode目录中新建一个文件StyleTemplateConfigHandler.cs:
public class StyleTemplateConfigHandler : IConfigurationSectionHandler
{
public object Create(object parent, object configContext, XmlNode section) {
return new StyleTemplateConfiguration(section);
}
}
// 映射 styleTemplates 结点的实体类
public class StyleTemplateConfiguration {
private XmlNode node; // styleTemplates 结点
private string defaultTheme; // 默认的主题名称
private string defaultStyle; // 站点默认风格名称
private HttpContext context;
private Dictionary<string,string> styleDic; // Key: 风格名称;Value: 主题名称
public StyleTemplateConfiguration(XmlNode node) {
this.node = node;
context = HttpContext.Current;
styleDic = new Dictionary<string, string>();
// 获取所有style结点的 name属性 和 theme属性
XmlNodeList styleList = node.SelectNodes("style");
foreach (XmlNode style in styleList) {
styleDic[style.Attributes["name"].Value] = style.Attributes["theme"].Value;
}
// 获取 站点默认风格 名称
defaultStyle = node.Attributes["default"].Value;
// 根据 风格名称 获取主题
defaultTheme = styleDic[defaultStyle];
}
// 获取所有风格名称
public ICollection<String> StyleNames {
get {
return styleDic.Keys;
}
}
// 根据风格名称获取主题名称
public string GetTheme(string styleName) {
return styleDic[styleName];
}
// 设置、获取 站点默认风格
public string DefaultStyle{
get {
return defaultStyle;
}
set { // 更改Web.Config中的默认风格,一般为站长才可以使用
XmlDocument doc = new XmlDocument();
doc.Load(context.Server.MapPath(@"~/web.config"));
XmlNode root = doc.DocumentElement;
XmlNode styleTemp = root.SelectSingleNode("styleTemplates");
styleTemp.Attributes["default"].Value = value;
doc.Save(context.Server.MapPath(@"~/web.config"));
}
}
// 获取默认主题名称
public string DefaultTheme {
get { return defaultTheme; }
}
// 根据页面路径获取其对应的 masterPage 的路径
public string GetMasterPage(string userTheme){
// 获取当前页面路径
string pagePath = context.Request.Path;
// 用于定位page结点的 XPath
string xpath = "style[@theme='" + userTheme + "']" + "/masterPages/page[@path='" + pagePath.ToLower() + "']";
// 获取与path属性相匹配的page结点
XmlNode pageNode = node.SelectSingleNode(xpath);
string master;
if (pageNode != null) {
// 获取page结点的 master属性的值
master = pageNode.Attributes["master"].Value;
return prepareMasterPath(master, userTheme);
} else
return null;
}
// 获取 Master Page 的路径
// MasterPagePath = 跟路径 + Theme路径 + 模板路径
private string prepareMasterPath(string masterPath, string userTheme) {
string path;
if (node.Attributes["masterRoot"] != null)
path = node.Attributes["masterRoot"].Value + "https://www.jb51.net/" + userTheme + "https://www.jb51.net/" + masterPath;
else {
if (userTheme != null) {
path = "~/" + userTheme + "https://www.jb51.net/" + masterPath;
} else {
path = "~/" + masterPath;
}
}
return path;
}
}