简化CommunityServer模板机制

     相信看过Community Server(以下简称CS)代码的人都会被它的架构模式深深吸引,它良好的架构为以后的扩展提供了无限的空间。但是对于初学者来说要想看懂CS的架构源码却非易事。就皮肤这一块就足以让初学者望而却步了,看着层层的继承、组合复杂的调用关系确实让人很难一下子就能看明白,更别提拿到现实项目中加以应用了。我也是一个初学者,前一段时间开发项目用到了皮肤,所以想拿CS的皮肤机制来实现,于是我把TemplatedWebControl.cs文件拷贝过来,打开一看就晕了,这么多东西都是干吗用的呢?仔细研究了一下发现原理并不复杂于是决定自己动手实现一套简单的,下边我就将我的实现思路和代码拿出来。

        首先我向菜鸟们讲一下CS模板的基本原理(老鸟就不用看了):

         原理很简单我用一个图表示一下

         TemplatedWebControl是CS皮肤控件基类,所有的CS皮肤控件都继承与TemplatedWebControl,它们其实就是一个自定义的WebControl,跟你自定义的分页控件阿什么的没什么区别,只是它们能够充当控件容器,它们可以根据ThemeName来装载不同的皮肤文件(ascx文件),那么基本调用流程是aspx页面上调用这些CS皮肤控件这些控件在根据ThemeName去装载ascx皮肤文件从而实现了皮肤机制.也就是说其实这些CS皮肤控件其实就是一个代理控件,aspx文件告诉它"我要调用ascx皮肤文件",CS皮肤控件接收到请求后根据当前的ThemeName的值去加载ascx文件最后返回给aspx。很简单吧?好了我们继续。

        原理搞清楚了,原来就是自己做了一个控件容器做代理,既然是控件容器那么非得自己继承WebControl和INamingContainer来开发吗?当然不是了,MS给我们提供了一个很好的容器控件——PlaceHolder,我们就用它做我们的ascx控件的代理吧,好了废话少说还是看具体的代码吧

首先我们也要跟CS一样建立一个CS皮肤控件的基类,当然肯定要比CS中的TemplatedWebControl简单的多,代码如下:

 

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.ComponentModel;

[assembly: TagPrefix(
"TestTemplate.Controls""Container")]
namespace TestTemplate.Controls
{
    
public abstract class BaseControlContainer:PlaceHolder
    {
        
public override Control FindControl(string id)
        {
            Control ctrl 
= base.FindControl(id);
            
if (ctrl == null && this.Controls.Count == 1)
            {
                ctrl 
= this.Controls[0].FindControl(id);
            }
            
return ctrl;
        }

        
private string _SkineName = "UserControls/Test.ascx";

        [Category(
"皮肤设置")]
        [Description(
"皮肤名称")]
        
public string SkineName
        {
            
get { return _SkineName;}
            
set { _SkineName = value; }
        }

        
protected override void OnLoad(EventArgs e)
        {
            Page 
= HttpContext.Current.Handler as System.Web.UI.Page;//获取当前上下文的Page
            this.Controls.Add(Page.LoadControl(_SkineName));//装载ascx控件
            AttachChildControls();
            DataHandle();
        }
        
protected abstract void AttachChildControls();//附加控件

        
protected abstract void DataHandle();//数据处理

    }
}

 

        这是个抽象类具体实现很简单,比如创建一个apcx文件相应的建立一个cs文件并继承BaseControlContainer实现AttachChildControls和DataHandle就搞定了!例如:

 

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

namespace TestTemplate.Controls
{
    
public class TestControl:BaseControlContainer
    {
        TextBox Textbox1;

        
protected override void AttachChildControls()
        {
     
//在这里查找ascx页面上的控件
            Textbox1 = FindControl("textbox1"as TextBox; 
        }

        
protected override void DataHandle()
        {
     
//这里对页面控件进行数据处理
            Textbox1.Text = "OK";
        }
    }
}

 


         OK!到此全部搞定,怎么样够简单吧?当然这个安全性不是特别好,比如当加载皮肤的时候路径错误的时候加载默认的阿这些都没有,如果需要的话可以加上,总之这个例子是本着简单来着,希望能起到抛砖引玉的作用。说得不对的地方欢迎大家指教。 

posted @ 2007-08-09 13:26  刘晓飞  阅读(648)  评论(0编辑  收藏  举报