还有一个需要熟悉的东西就是控件的渲染流程,你需要理解他,不管怎样,你都要理解他,请暂时放下你的吉他,理解它,真的,实在太重要了。
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>
附图片: