theme样式肯定是一个好的博客系统应该有重要的因素。在BlogEngine中提供了好几套自定义的主题模板(预览如下图所示),这一篇我们就来探究BE中的主题切换是怎样实现的。
BE使用了Asp.net中的模板机制来实现主题功能。
具体实现是:定义一个Page基类,在这个基类中的PreInit事件中根据用户设置的theme名称到对应的地方读取这个theme文件夹下面的site.master等等文件。将site.master设置为其母页。这样所有继承于page基类的页面的样式都会改变。而具体的一些article页面则是一个<asp:Content />,这样在每次加载页面的时候就能根据用户设置的不同主题加载不同的样式了。我们来举个例子操作一下:
1.首先新建一个网站项目
按上图所示那样新建一个themes文件夹,用来存放不同的主题样式模板。里面具体的内容就是你如何定义网站外观的css,master文件了。为了方便,我这里是直接从BE的源码中拿过来用的。下面是site.master的内容:
<body>
<div id="mainpage">
<div id="header">
<a href="<%=Utils.AbsoluteWebRoot %>">
<h1>
"blog name"
</h1>
</a>
<div class="description">
"blog description"</div>
</div>
<div id="menulinks">
<a <%=MenuClass("default.aspx")%> href="<%=Utils.AbsoluteWebRoot %>" rel="home"><span>
home</span></a>
<div class="menulines">
</div>
<a <%=MenuClass("archive.aspx")%> href="<%=Utils.AbsoluteWebRoot %>archive.aspx"><span>
archive</span></a>
<div class="menulines">
</div>
<a <%=MenuClass("search.aspx")%> href="<%=Utils.AbsoluteWebRoot %>search.aspx"><span>
search/span></a>
<div class="menulines">
</div>
<a <%=MenuClass("contact.aspx")%> href="<%=Utils.AbsoluteWebRoot %>contact.aspx"><span>
contact</span></a>
<div class="menulines">
</div>
</div>
<form id="Form1" runat="Server" class="body">
<div id="mainarea">
<div id="contentarea">
<!--这里是具体内容存放的地方,所有放在这里的内容的contentID必须是 cphBody -->
<asp:ContentPlaceHolder ID="cphBody" runat="server" />
</div>
<div id="sidebar">
</div>
</div>
</form>
<div id="footer">
<div id="footerleft">
c 2010. All Rights Reserved. <a runat="server" id="aLogin" />
</div>
<div id="footerright">
Powered by <a href="http://www.blogyi.net">BlogYi.NET</a> ver:2, original powered
by <a href="http://www.dotnetblogengine.net">BlogEngine.NET</a>.</div>
</div>
</div>
</body>
上面我加了注释的地方就是具体内容存放的地方,其他的都是不同的主题不同的实现。页面具体再执行的时候,最后会将contentId为cphBody的内容填充到这里。有了不同的主题,我们还需要在一个地方指定使用网站到底加载哪个主题里面的site.master,这个就是basepage类做的事情了,且往下看。
2.新建一个BasePage类
这个类继承Page基类。用于在页面初始化的时候加载特定的主题模板。下面是BasePage具体实现的内容:
public class BasePage :Page
{
string theme = "stardard";
protected override void OnPreInit(System.EventArgs e)
{
//加载主题
this.MasterPageFile = string.Format("{0}themes/{1}/site.master", Utils.RelativeWebRoot, this.theme);
base.OnPreInit(e);
}
}
可以看到,应用于主题这一块。BasePage只是在OnPreInit方法里面加载一个site.master并将它设置为MasterPageFile以便将样式应用于所有继承于BasePage的页面。
3.新建一个具体内容的显示页面default.aspx,他的内容如下:
<%@ Page Title="Home Page" Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="AspNetThemeTest._Default" %>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="cphBody">
<h2>
Welcome to ASP.NET!
</h2>
<p>
To learn more about ASP.NET visit <a href="http://www.asp.net" title="ASP.NET Website">www.asp.net</a>.
</p>
<p>
You can also find <a href="http://go.microsoft.com/fwlink/?LinkID=152368&clcid=0x409"
title="MSDN ASP.NET Docs">documentation on ASP.NET at MSDN</a>.
</p>
</asp:Content>
真正所有的内容其实都是写在
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="cphBody">
</asp:Content>
里面的,这个也就是我们第一步site.master里面的那个<asp:ContentPlaceHolder ID="cphBody" runat="server" />了,页面最后会将这里面的内容填充到site.master对应的部分。从这里看起来,asp.net的母版页很利于页面的模块化呢 :)
最后看看实现的效果吧: