代码改变世界

BlogEngine中自定义主题的实现

2011-03-13 10:17  MichaelYin  阅读(430)  评论(0编辑  收藏  举报

BlogEngine中通过一种较灵活的方式实现了可扩展的自定义主题的实现的功能,用户只需要从网上下载相应的样式包,然后放到对应的文件夹下就能够实现对显示主题的切换。

在Web项目的themes文件夹下面有对应的各个主题的文件夹,文件夹里面有相应的主题所需要的CSS,图片等文件,另外还有三个文件,site.master,CommentView.ascx和PostView.ascx。其中除了site.master以外,另外两个都是没有后台代码的,当时对于这个表示有点不理解,后来看了一下才明白,原来前台代码上面的标记,CodeFile指定了前台代码对应的后台代码的地址,而Inherits则制定了前台代码对应后台的类名称,CommentView.ascx和PostView.ascx虽然没有指定相应的后台的文件,但是通过Inherits指定了对应的类,也正是通过这种结构使得CommentView.ascx和PostView.ascx的编写者可以直接使用BlogEngine中现有的类而自己专注于界面显示。

image

post.aspx是显示单篇Post的页面,现在就以这个为例子来解释一下自定义样式的实现功能。

页面的Page_Load事件中通过读取BlogEngine的themes来动态从theme中来动态的把用户控件添加到post.aspx页面中,并且赋给其属性相应的值,而theme中所有的样式的显示post的用户控件PostView.ascx都和PostViewBase这个类关联,提供了一个统一的框架。

                string path = Utils.RelativeWebRoot + "themes/" + BlogSettings.Instance.Theme + "/PostView.ascx";

				PostViewBase postView = (PostViewBase)LoadControl(path);
				postView.Post = Post;
				postView.ID = Post.Id.ToString().Replace("-", string.Empty);
				postView.Location = ServingLocation.SinglePost;
				pwPost.Controls.Add(postView);

post.aspx用到了在User Controls文件夹下有CommentView的用户控件(这个和theme中的同名控件的功能略有不同,注意区别),这个控件的功能主要是提供显示Post对应的comment和提供添加comment的功能。它通过CallBack的机制来使得无刷新的动态添加comment成为可能。Callback中返回的字符串也是动态读取Theme中相应的主题的CommentView.ascs.

     string path = Utils.RelativeWebRoot + "themes/" + BlogSettings.Instance.Theme + "/CommentView.ascx";

        CommentViewBase control = (CommentViewBase)LoadControl(path);
        control.Comment = comment;
        control.Post = Post;

        using (StringWriter sw = new StringWriter())
        {
            control.RenderControl(new HtmlTextWriter(sw));
            _Callback = sw.ToString();
        }

总的来说把post.aspx的功能拆开来看就行,PostViewBase是和Post显示相关的类,通过theme中的文件夹中的用户控件动态添加到post中,而BlogEngine.Core.Web.Controls.CommentViewBase则是管理的comment的显示,通过和theme中的CommentView.ascx动态添加到User controls中的CommentView.ascx(该控件在post.aspx)中来实现根据相应的样式名来添加相应的用户控件,并且实现良好的扩展性。

image

至于site.master的加载则是在所有需要使用统一样式的页面里面的page_load中写类似上述的代码,不过使用一个页面基类可以更好的完成这个功能,所以BlogBasePage中完成了这个功能。