您的位置:首页 > 编程语言 > ASP

黑马程序员之ASP.NET学习笔记:控件树的生成

2012-09-29 08:29 561 查看
--------------------------------2345王牌技术员联盟2345王牌技术员联盟、期待与您交流!------------------------------------

控件树的生成

——页面类对象,通过控件树的方式,帮我们封装了整个页面的HTML源代码和C#代码(都封装到页面类对象的控件集合属性中,那么要生成HTML代码的时候,只需要循环遍

历整个控件树,并调用每个控件的__Render__(呈现)方法获得每个控件的HTML代码,就可以拼成一个完整的HTML代码了。)

前台页面最上方有 Inherist(继承) = "类名" 指定了前台页面类继承的对象

如果C盘没有程序集,浏览器访问网站的时候,服务器会自动把网站编译成程序集(DLL) 浏览器请求————》服务器在内存中找网站程序集————》没有的就到C盘找————》没有就编译

编译好的程序集中有两个比较熟悉的类,一个是以 页面名 命名的类,一个是以 页面名_aspx 命名的类(通过反编译网站程序集看到)

1.FirstForm(页面名)类 (后台文件类)

对应了我们编写的后台文件里的内容

继承于Page类,并实现了 IRequiresSessionState 接口

后台文件类之所以能通过 this.控件ID 调用前台页面控件,是因为前台控件(runat="server" 的控件)是以后台文件类变量的方式存在的。前台页面类也可以访问到父类(后台文件类)的非私有成员(方法、属性),通过写在前台页面<%%>中实现

当浏览器请求该页面的时候,服务器通过反射在程序集中创建出 前台页面类对象,由于前台页面类继承于 后台文件类,所以编译器会自动创建出它的父类对象——后台文件类

2.前台页面类

前台页面类中有个名为 __BuidControlTree 的方法,页面被请求的时候,通过调用该方法来组织整个页面的HTML代码(创建控件树)

3.控件树

控件就是一个对象

控件树负责整个页面的内容(前台页面类中的 __BuidControlTree 方法 )

在浏览器中的DOM树中,每个节点都有一个 childNodes集合属性,用来保存当前节点的子节点 (每一个节点中都必须有一个子节点集合,这样才能生成一颗树)

在.net中生成控件树的时候,也必须要生成一个个的对象,这些对象里面,也必须包含子控件集合,以方便的安装子控件

在__BuidControlTree方法中,传入了当前页面对象(__ctrl),并把该对象转成了一个 IParserAccessor 接口,该接口中有一个名为 AddParsedSubObject的方法(添加子节点),由此可知,当前页面对象(__ctrl)中,肯定会有一个集合,用来存放子节点

该集合在它(前台页面类)的父类 后台页面类 的父类 Page 的父类 TemplateControl 的父类 Control类中,名字为 ControlCollection 的集合

页面本身就是控件,它的属性 ControlCollection集合(存在于父类Control中) 存放了它的子控件

__BuildControlTree方法首先给该集合添加了一个 LiteralControl 对象,它里面存放的是HTML最上方的那段HTML代码(从 <!DOCTYPE 一直到 <html> 的开始标签),该标签下方的<head>中有 runat="server" ,head将作为一个对象存放在集合里面,所以上面的html代码都作为字符串封装到了 LiteralControl 中,并将它作为一个子节点保存在集合中,可以把 LiteralControl 理解为一个字符串控件

添加了 runat="server" 的控件,编译之后,就会变成一个相对应类型的对象,并作为子节点存入集合中

创建HtmlHead对象的时候,调用了this.__BuildControl__control2方法,该方法中,new了一个名为head的HtmlHead对象,并在该方法中调用this.__BuildControl__control3方法,创建了一个名为title的HtmlTitle的对象,随后把head转成IParserAccessor接口,将title加入head的控件集合中,返回head

在 __BuildControl__control3中,返回了一个专门的类型 HtmlTitle

head创建完成后,被转成接口的当前页面的对象(__ctrl)调用AddParsedSubObject方法,把head加入到集合中

因为<body>并没有 runat="server" ,所以把它封装在LiteralControl中,并加入集合

在 __BuildControlTree 方法中,调用 __BuildControlform1 方法,创建了页面中ID=form1的表单的对象,加入当前页面集合

由于<body>是作为文本对象存在的,不会有自己的子节点,所以<body>中的有runat="server"的<form>表单对象被加入了当前页面的集合中(如果form表单没有runat="server",那么也将被封装成字符串控件加入到当前页面的集合中,而它有runat="server"的子节点将作为对象直接存入当前页面的集合中————自己猜的)

在 __BuildControlform1方法中,首先创建了form对象,并给父类(后台文件类)中的属性from1赋值(base.form1 = form;),随后分别创建了表单中的其他节点,把form对象转成 IParserAcessor 接口,并调用 AddParsedSubObject 方法,把属于 form的对象加入到 form对象的集合中,返回form

在返回form之前,有一句非常重要的代码 (form.SetRenderMethodDelegate(new RenderMethod(this.__Renderform1));),它向当前表单对象追加了一个委托,委托上注册了一个方法(__Renderform1),该方法中,执行了前台页面中<%%>中的代码,并将没有runat="server"的控件直接以字符串的形式呈现,还调用了from的集合中的元素(有runat="server"的属于form1表单的服务器控件的对象)的呈现(RenderControl)方法,将它们加入到浏览器的缓存中(HtmlTextWriter)

(在前台页面<%%>中有“=”或有"Response.Write”的时候,就有可能在控件树里面调用控件对象的呈现委托方法,向里面追加一个呈现的方法)

(服务器控件的对象,都有对应的呈现方法,而<$=$>中的代码却没有,只能追加一个呈现方法,执行代码,把结果转成HTML代码)

呈现————将服务器端控件类对象转成对应的html代码

form表单对象创建完毕后,将之加入当前页面类的集合中(通过转成IParserAcessor接口的对象调用AddParsedSubObject方法)

由于演示页面已经没有内容了,所以最后将</body>等html结束代码封装到LiteralControl字符串控件中,加入当前页面类的集合中,控件树创建完毕

---------------------------------------------------
2345王牌技术员联盟、2345王牌技术员联盟、期待与您交流!---------------------------------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: