让阳光指引生命的每一刻,乘着风,跟随我融化空气

美丽的地球

实现自己的MasterPage和WebPart控件,开发没有aspx,ascx的web程序,全部由自定义控件生成,并且支持MasterPage摸版功能。

    实现自己的MasterPage和WebPart控件


    开发没有aspx,ascx的web程序,全部由自定义控件生成,并且支持MasterPage摸版功能。

 

    asp.net提供的MasterPage确实是一个好的功能,我也很需要这样的东西,可是我想更多的扩展一下,以实现自己的MasterPage控件。需要支持可以动态更改title,动态添加关键字,动态添加css, 动态添加script。这是个不错的想法,如何实现?

 

    那么我们回到asp.net服务器控件的架构上来,先来熟悉下它,理解它的生命周期,这个很重要,我可不开玩笑,因为我需要对它加以利用,动点小手术,因此你必须必须理解它,否则,请放下键盘,拿起你的吉他,一边玩儿^_*。

 

    在你放下键盘那起吉他之前,请把我这篇文章看完,好了,在这里我只谈2.0的相关部分。

 

    ===================控件生命周期开始===================
    控件构造器
    初始化阶段 Init事件
    -----加载视图状态
    -----加载回传数据
    加载阶段 Load事件
    -----引发数据修改事件
    -----引发回传事件
    预生成阶段 PreRender
    保存视图状态
    生成阶段
    卸载阶段 Unload
    释放
    ===================控件生命周期结束===================

    以上的东西写的文章已经很多了,我只凭记忆把他写出来,不对的地方,大家指正。


    还有一个需要熟悉的东西就是控件的渲染流程,你需要理解他,不管怎样,你都要理解他,请暂时放下你的吉他,理解它,真的,实在太重要了。


    Control控件暴露了一个公共的RenderControl(HtmlTextWrite write)方法,用与生成html到输出流。
这个方法是这么定义的,这里我说的是2.0。
    RenderControl(HtmlTextWrite write)
    {
        if(可视)
        {
           继续Render(write);
        }
    }

    看到了,如果当前控件的Visible属性设置为true的话,它才会调用Render方法,注意这个方法是受保护的,不是由你来调用的,不过你还是有机会调用他的,放心,继续看下面。
    除非你继承Control控件,否则你只能近接的调用他,也就是由Page框架或是Control的RenderControl方法调用它。

    Render方法是这样的:
    Render(HtmlTextWrite write)
    {
        继续RenderChildren(write);   
    }


    看上去是去生成子控件,确实如此,RenderChildren是这样的:

    RenderChildren(HtmlTextWrite write)
    {
        foreach(Control control in Controls)
        {
            RenderControl(write); //这里我近接的调用了Render方法,虽然你是受到保护的。可我还是调用啦
        }
    }


    看到了,RenderChildren里面有回去了,原来Control控件的渲染流程是这样的啊,通过判断自己的Contros属性来不断的调用,只到自己的所有子控件都调用到,好家伙。

    以上提到的是写web服务器控件的必备知识,很基础,但是你不可以小视他,一点要过他,你才会写出好的控件来。

 

    web开发的底层就是一堆的HTML标签,无论是jsp还是asp.net都是对html某种方式的包装,是HTML的产物,IE浏览器访问web服务器,最终我们接收到的还是html文本。IE然后通过渲染引擎解释这些标签,在屏幕上展现出来可见的效果。

 

    asp.net提供了很多服务器控件,提供了很多所见即所得的功能,丰富了web应用程序的开发。

 

    这些服务器控件架构,有些地方我们是可以利用的,就是说我们自己可以来扩展,写出符合自己需求的控件来。asp.net web Control带有太多的样式属性,比如说Panel控件,就有如Color,Width等各种属性,因为它继承于WebControl控件。如果你需要这么一个Panel类似的控件 ,可是你有不需要那些从WebControl继承而来的属性,那么好的选择就是你直接继承Control控件,这个控件只有基本的控件架构,而没有那些可见的web样式属性。

 

    恰好我需要这样的控件,因为我不需要那些可见的web样式属性,因为我要生成的控件通过CSS文件来控制的,也就是所有的空间都只输出Div这个标签。如果这样的标签:

    <div id="id" class="class">
        <div id="id_children" class="class_container">
            <ul><li></li></ul>
        </div>
        <div id="id_children" class="class_container"> </div>
    </div>

    如上,标签时可以嵌套的。

 

    到这里开始自己动手,创建自己的MasterPage控件,因为我不需要样式控制,所以我选择继承Control控件,以便于利用他的架构模型和渲染模型。


    public class MasterControl : Control
    {
        #region //字段
        protected string id;
        protected string title;
        protected string keyword;
        protected List<string> css;
        protected List<string> script;
        protected Page page;
        #endregion
        //略去N行代码...
        #region //重写基类方法
        protected override void Render(HtmlTextWriter writer){....}
        #endregion

        #region //私有方法
        private void GenericHeadHTML(HtmlTextWriter writer)
        {
            writer.AddAttribute("http-equiv", "Content-Type");
            writer.AddAttribute(HtmlTextWriterAttribute.Content, "text/html; charset=utf-8");
            writer.RenderBeginTag(HtmlTextWriterTag.Meta);
            writer.RenderEndTag();

            writer.WriteLine();

            writer.AddAttribute("http-equiv", "Content-Language");
            writer.AddAttribute(HtmlTextWriterAttribute.Content, "zh-CN");
            writer.RenderBeginTag(HtmlTextWriterTag.Meta);
            writer.RenderEndTag();

            writer.WriteLine();

            writer.AddAttribute(HtmlTextWriterAttribute.Name, "keywords");
            writer.AddAttribute(HtmlTextWriterAttribute.Content, keyword);
            writer.RenderBeginTag(HtmlTextWriterTag.Meta);
            writer.RenderEndTag();

            writer.WriteLine();

            writer.RenderBeginTag(HtmlTextWriterTag.Title);
            writer.Write(title.Remove(title.Length - 3));
            writer.RenderEndTag();

            writer.WriteLine();

            foreach (string itemCss in css)
            {               
                writer.AddAttribute(HtmlTextWriterAttribute.Rel, "stylesheet");
                writer.AddAttribute(HtmlTextWriterAttribute.Href, itemCss);
                writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/css");
                writer.AddAttribute("media", "all");
                writer.RenderBeginTag(HtmlTextWriterTag.Link);
                writer.RenderEndTag();
                writer.WriteLine();
            }

            foreach (string itemScript in script)
            {
                writer.WriteLine("<script type=\"text/javascript\" src=\"" + itemScript +"\" ></script>");
            }
        }
        #endregion
    }

 

    namespace MINGMING.MUSIC.Contorls
    {
        public class MasterPage : MasterControl
        {
            #region //字段
            protected ControlContainerBase headerLayout, contentLayout, footerLayout;
            #endregion

            #region //构造方法
            public MasterPage(Page page)
                : base(page)
            {
                headerLayout = new FooterLayout(this);
                contentLayout = new ContentLayout(this);
                footerLayout = new HeaderLayout(this);
            }
            #endregion
        }
    }

 

页面调用测试:

        #region 字段
        protected RequestContext requestContext; //web部件需要的请求上下文
        protected NewsPartZone news1, news2, news3, news4; //web部件
        protected MasterControl masterPage; //MasterPage模板控件
        #endregion

        #region //重写基类方法
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            requestContext = new RequestContext();
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            Initialize(); //初始化
        }
        #endregion

        #region //初始化
        private void Initialize()
        {
            #region
            /*
            NewsEntity newsEntity = new NewsEntity();
            NewsCategoryEntity newsCategoryEntity = new NewsCategoryEntity();
            List<NewsEntity> newsList ;
            List<NewsCategoryEntity> newsCategorys ;
            int totalRecord;

            newsEntity.ID = 3;
            newsEntity.Title = "testTitle88888";
            newsEntity.Content = "testContent88888";
            newsEntity.Author = "liuming";
            newsEntity.ImageFilename = null;
            newsEntity.HTMLFilename = "888880100.html";
            newsEntity.Category.ID = 1;
            newsEntity.Template.ID = 1;

            newsBLL.Add(newsEntity);
            newsCategorys = newsCategoryBLL.GetAll();
            newsList = newsBLL.GetPage(1, true, 1, 10, out totalRecord);
            */
            #endregion

            masterPage = new MasterPage(this); //自定义的MasterPage控件,为当前页设置MasterPage
            masterPage.ID = "layout"; //页面ID
            masterPage.Title = "test Title"; //页面标题
            masterPage.Keyword = "key1,key2,key3"; //页面关键字
            masterPage.Css.Add("/Resources/Css/main.css"); //当前页面所需要的样式表文件
            masterPage.Script.Add("/Resources/Script/main.js"); //当前页面所需要的脚本文件

            requestContext.PageHit.PageIndex = 1; //部件需要的请求上下文
            requestContext.PageHit.PageSize = 2;

            news1 = new NewsPartZone(); //部件1
            news1.ID = "news_partzone"; //部件1 ID
            news1.IsShowHeader = true; //是否显示部件的Header区域
            news1.Title = "部件1"; //Header区域的文字
            news1.Parent = masterPage.Controls[1] as ControlContainerBase; //部件的父容器
            news1.RequestContext = requestContext; //请求上下文
            news1.MasterPage = masterPage; //部件的MasterPage
            news1.Initialize(); //将所有子控件加到控件树,然后将自己加到MasterPage里面,也就是把自己加到Parent属性所指向的对象

            requestContext.PageHit.PageIndex = 1;
            requestContext.PageHit.PageSize = 3;

            news2 = new NewsPartZone(); //部件2
            news2.ID = "news_partzone2";          
            news2.Title = "部件2"; //这个title不会显示出来
            news2.Parent = masterPage.Controls[1] as ControlContainerBase;
            news2.RequestContext = requestContext;
            news2.MasterPage = masterPage;
            news2.Initialize();

            news3 = new NewsPartZone(); //部件3
            news3.ID = "news_partzone3";
            news3.IsShowHeader = true;
            news3.Title = "部件3";
            news3.Parent = masterPage.Controls[1] as ControlContainerBase;
            news3.RequestContext = requestContext;
            news3.MasterPage = masterPage;
            news3.Initialize();


            requestContext.PageHit.PageIndex = 1;
            requestContext.PageHit.PageSize = 4;

            news4 = new NewsPartZone(); //部件4
            news4.ID = "news_partzone3";
            news4.Title = "部件3"; //这个title不会显示出来
            news4.Parent = masterPage.Controls[2] as ControlContainerBase;
            news4.RequestContext = requestContext;
            news4.MasterPage = masterPage;
            news4.Initialize();
        }
        #endregion

 

最终生成的网页代码如下:
下面的这个HTML标签全部由程序生成,所有的字符,包括头部区域的。都是从服务器端动态生成出来的。

 

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta http-equiv="Content-Language" content="zh-CN" />
  <meta name="keywords" content="key1,key2,key3" />
  <title>
   test Title - this.owner.MasterPage.Title - this.owner.MasterPage.Title - this.owner.MasterPage.Title - this.owner.MasterPage.Title
  </title>
  <link rel="stylesheet" href="/Resources/Css/main.css" type="text/css" media="all" />
  <link rel="stylesheet" href="/Resources/Css/newsList.css" type="text/css" media="all" />
  <link rel="stylesheet" href="/Resources/Css/newsList.css" type="text/css" media="all" />
  <link rel="stylesheet" href="/Resources/Css/newsList.css" type="text/css" media="all" />
  <link rel="stylesheet" href="/Resources/Css/newsList.css" type="text/css" media="all" />
  <script type="text/javascript" src="/Resources/Script/main.js" ></script>
  <script type="text/javascript" src="/Resources/Script/news.js" ></script>
  <script type="text/javascript" src="/Resources/Script/news.js" ></script>
  <script type="text/javascript" src="/Resources/Script/news.js" ></script>
  <script type="text/javascript" src="/Resources/Script/news.js" ></script>

 </head>
 <body>
  <div id="layout">
   <div id="layout_footer">
    Page_Header - 这里是页头
   </div>
   <div id="layout_content">
    <div id="news_partzone" class="partzone">
     <div id="news_partzone_header" class="partzone_header">
      部件1
     </div>
     <div id="news_partzone_content" class="partzone_content">
      <div id="news_list_container">
       <ul><li>网络歌曲“黑色巧克力“ 07 - 颜绘唐</li><li>网络歌曲“黑色巧克力“ 06 - 颜绘唐</li></ul>
      </div>
      <div id="page_hit">

      </div>

     </div>
    </div><div id="news_partzone2" class="partzone">
     <div id="news_partzone2_content" class="partzone_content">
      <div id="news_list_container">
       <ul><li>网络歌曲“黑色巧克力“ 07 - 颜绘唐</li><li>网络歌曲“黑色巧克力“ 06 - 颜绘唐</li><li>网络歌曲“黑色巧克力“ 05 - 颜绘唐</li></ul>
      </div>
      <div id="page_hit">

      </div>

     </div>
    </div><div id="news_partzone3" class="partzone">
     <div id="news_partzone3_header" class="partzone_header">
      部件3
     </div>
     <div id="news_partzone3_content" class="partzone_content">
      <div id="news_list_container">
       <ul><li>网络歌曲“黑色巧克力“ 07 - 颜绘唐</li><li>网络歌曲“黑色巧克力“ 06 - 颜绘唐</li><li>网络歌曲“黑色巧克力“ 05 - 颜绘唐</li></ul>
      </div>
      <div id="page_hit">

      </div>

     </div>
    </div>
   </div>
   <div id="layout_header">
    Page_Footer - 这里是页脚<div id="news_partzone3" class="partzone">
     <div id="news_partzone3_content" class="partzone_content">
      <div id="news_list_container">
       <ul><li>网络歌曲“黑色巧克力“ 07 - 颜绘唐</li><li>网络歌曲“黑色巧克力“ 06 - 颜绘唐</li><li>网络歌曲“黑色巧克力“ 05 - 颜绘唐</li><li>网络歌曲“黑色巧克力“ 04 - 颜绘唐</li></ul>
      </div>
      <div id="page_hit">

      </div>

     </div>
    </div>
   </div>

  </div>
 </body>
</html>

 

附图片:

 

 

 

 

 

 

 

 

 


 

posted on 2008-08-09 18:17 天真的好蓝啊 阅读(2175) 评论(7) 编辑 收藏

My Links

Blog Stats

News