第二篇:呈现内容_第一节:Control呈现
一、Control的呈现过程
在上个章节““生死有序”的控件生命周期”中,我们提到Render是控件开发的主角,但在控件树的“合成模式(Composite)”部分这位主角却缺席了(戏份太多的缘由)。哦,好吧。主角现在登场。
1)控件树呈现的“合成模式(Composite)”
控件树的呈现过程是一个华丽的大圈,它从RenderControl(HtmlTextWriter writer)开始、从RenderChildrenInternal(HtmlTextWriter writer, ICollection children)结束。其过程涉及Control类的6个方法。期间种种,我们慢慢道来。
- public virtual void RenderControl(HtmlTextWriter writer);
- protected void RenderControl(HtmlTextWriter writer, ControlAdapter adapter);
- private void RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter);
- protected internal virtual void Render(HtmlTextWriter writer);
- protected internal virtual void RenderChildren(HtmlTextWriter writer);
- internal void RenderChildrenInternal(HtmlTextWriter writer, ICollection children);
①Page中RenderControl()的调用:故事开始的地方
我们知道,Page类实现了IHttpHandler接口,所以ASP.NET框架得以最终把对请求进行响应的任务通过调用Page的ProcessRequest()方法交给aspx页面。在Page执行ProcessRequest()方法处理请求时,它完成了大量的工作:维持状态、处理回传数据、处理事件等等,而最后一个环节是基于HttpContext中Response.Output流创建HtmlTextWrite,并调用Page从Control类那里继承来的RenderControl()方法把页面内容发送给请求者。
- //......呈现的入口
- this.RenderControl(this.CreateHtmlTextWriter(this.Response.Output));
②RenderControl(HtmlTextWriter writer):
- [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
- public virtual void RenderControl(HtmlTextWriter writer)
- {
- this.RenderControl(writer, this.Adapter);
- }
③RenderControl(HtmlTextWriter writer, ControlAdapter adapter):
- protected void RenderControl(HtmlTextWriter writer, ControlAdapter adapter)
- {
- if (this.flags[16] || this.flags[512]) //if(this.Visible == false):详见下面附的代码
- {
- this.TraceNonRenderingControlInternal(writer);
- return;
- }
- HttpContext httpContext = (this.Page == null) ? null : this.Page._context;
- if (httpContext != null && httpContext.TraceIsEnabled)
- {
- int bufferedLength = httpContext.Response.GetBufferedLength();
- this.RenderControlInternal(writer, adapter);
- int bufferedLength2 = httpContext.Response.GetBufferedLength();
- httpContext.Trace.AddControlSize(this.UniqueID, bufferedLength2 - bufferedLength);
- return;
- }
- this.RenderControlInternal(writer, adapter);
- }
- [Bindable(true), DefaultValue(true), WebCategory("Behavior"), WebSysDescription("Control_Visible")]
- public virtual bool Visible
- {
- get
- {
- return !this.flags[16] && (this._parent == null || this.DesignMode || this._parent.Visible);
- }
- set
- {
- if (this.flags[2])
- {
- bool flag = !this.flags[16];
- if (flag != value)
- {
- this.flags.Set(32);
- }
- }
- if (!value)
- {
- this.flags.Set(16);
- return;
- }
- this.flags.Clear(16);
- }
- }
- private const int invisible = 16;
- private const int notVisibleOnPage = 512;
④RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter):
- private void RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
- {
- try
- {
- this.BeginRenderTracing(writer, this);
- if (adapter != null) //控件是否有相关的呈现适配器
- {
- //如果有,呈现适配器调用相关的呈现方法呈现控件
- adapter.BeginRender(writer);
- adapter.Render(writer);
- adapter.EndRender(writer);
- }
- else
- {
- //如果没有,使用控件类本身的呈现方法呈现控件
- this.Render(writer);
- }
- }
- finally
- {
- this.EndRenderTracing(writer, this);
- }
- }
⑤Render(HtmlTextWriter writer):
- [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
- protected internal virtual void Render(HtmlTextWriter writer)
- {
- this.RenderChildren(writer);
- }
⑥RenderChildren(HtmlTextWriter writer):
- protected internal virtual void RenderChildren(HtmlTextWriter writer)
- {
- ICollection controls = this._controls;
- this.RenderChildrenInternal(writer, controls);
- }
⑦RenderChildrenInternal(HtmlTextWriter writer, ICollection children):
- internal void RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
- {
- if (this.RareFields != null && this.RareFields.RenderMethod != null)
- {
- writer.BeginRender();
- this.RareFields.RenderMethod(writer, this);
- writer.EndRender();
- return;
- }
- if (children != null) //如果子控件的集合不为空,继续递归;若为空,结束递归。
- {
- foreach (Control control in children)
- {
- control.RenderControl(writer);
- }
- }
- }
2)控件树呈现的简单模型
上面我们分析了Control利用“合成模式”递归生成控件树的全过程,也注意到Control类用于呈现的6个方法中有三个是虚方法,它们是开发控件我们可重写改变呈现逻辑的部分。首先,我们用伪代码概述下Control类中这三个方法呈现控件的模型。
- public virtual void RenderControl(HtmlTextWriter writer)
- {
- if (this.Visible)
- {
- this.Render(writer);
- }
- }
- protected internal virtual void Render(HtmlTextWriter writer)
- {
- --><div...
- this.RenderChildren(writer);
- --></div>
- }
- protected internal virtual void RenderChildren(HtmlTextWriter writer)
- {
- if (this._controls != null)
- {
- foreach (Control control in this._controls)
- {
- control.RenderControl(writer);
- }
- }
- }
二、从Control类派生"相册"控件
1)“相册”控件初实现
通过上面的分析,很显然我们需要重写Render()方法的呈现逻辑,以输出我们期待呈现的内容。对,你一定还记得初始ASP.NET控件开发中的“HelloWorld”吧?
那你应该能写出这样的代码:
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Text;
- using System.Web;
- using System.Web.UI;
- using System.Web.UI.WebControls;
- namespace CustomServerControls
- {
- public class Albumn : Control
- {
- protected override void Render(HtmlTextWriter writer)
- {
- writer.WriteLine(@"<div style=""text-align:center;width:194px;height:194px;background:url(Images/background.gif) no-repeat left"">");
- writer.WriteLine(@" <img src=""Images/Nature.jpg"" width=""160"" height=""160"" style=""border:none;padding:0px;margin-top:16px;"">");
- writer.WriteLine(@"</div>");
- }
- }
- }
2)HtmlTextWriter的四个方法
上面,我们已经实现了一个很不完善的“相册”控,勉强实现了HTML代码的输出。但这样用字符串来组织输出内容我们不能利用IDE的智能感知功能,也不能在编码时捕获错误,更谈不上不同浏览器生成不同的HTML代码。哪应该怎样呢?其实,HtmlTextWriter类已经封装了很多生成HTML代码的方法。下面介绍四个最常用的:
①RenderBeginTag():生成HTML起始标签
- public virtual void RenderBeginTag(HtmlTextWriterTag tagKey);
- public virtual void RenderBeginTag(string tagName);
②RenderEndTag():生成HTML结束标签
- public virtual void RenderEndTag();
③AddAttribute():为HTML标签添加属性
- public virtual void AddAttribute(string name, string value);
- public virtual void AddAttribute(string name, string value, bool fEndode);
- public virtual void AddAttribute(HtmlTextWriterAttribute key, string value);
- public virtual void AddAttribute(HtmlTextWriterAttribute key, string value, bool fEncode);
④AddStyleAttribute():为HTML标签添加样式属性
- public virtual void AddStyleAttribute(string name, string value);
- public virtual void AddStyleAttribute(HtmlTextWriterStyle key, string value)
- 值得注意的是:当需要向一个标签添加属性和样式属性时,在调用生成HTML其实标签的RenderBeginTag()方法之前先调用AddAttribute()方法和AddStyleAttribute()方法添加所有必要的属性和样式属性。
3)“相册”控件再实现
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Text;
- using System.Web;
- using System.Web.UI;
- using System.Web.UI.WebControls;
- namespace CustomServerControls
- {
- public class Albumn : Control
- {
- protected override void Render(HtmlTextWriter writer)
- {
- //最外层DIV的样式属性
- writer.AddStyleAttribute(HtmlTextWriterStyle.TextAlign, "center");
- writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "194px");
- writer.AddStyleAttribute(HtmlTextWriterStyle.Height, "194px");
- writer.AddStyleAttribute("background", "url(Images/background.gif) no-repeat left");
- //最外层的Div开始
- writer.RenderBeginTag(HtmlTextWriterTag.Div);
- //IMG标签的属性和样式属性
- writer.AddAttribute(HtmlTextWriterAttribute.Src, "images/nature.jpg");
- writer.AddAttribute(HtmlTextWriterAttribute.Width, "160");
- writer.AddAttribute(HtmlTextWriterAttribute.Height, "160");
- writer.AddStyleAttribute(HtmlTextWriterStyle.BorderStyle, "none");
- writer.AddStyleAttribute(HtmlTextWriterStyle.Padding, "0px");
- writer.AddStyleAttribute(HtmlTextWriterStyle.MarginTop, "16px");
- //生成Img标签
- writer.RenderBeginTag(HtmlTextWriterTag.Img);
- writer.RenderEndTag();
- //最外层DIV结束
- writer.RenderEndTag();
- }
- }
- }
第二篇:呈现内容_第一节:Control呈现的更多相关文章
- 第二篇:呈现内容_第二节:WebControl呈现
一.WebControl的呈现过程 WebControl派生自Control类,所以WebControl的呈现功能基于Control的呈现逻辑之上,但有了比较大的扩展. 首先,WebControl重写 ...
- 机器学习_第一节_numpy
今天学了机器学习第一节, 希望能够坚持下去,其实不在乎课程是什么?关键要坚持下去 今天主要学了对矩阵的一些操作, 用的库是numpy 开始从头到尾捋一遍, 作者说的很有道理,学计算机,动手能力要强,所 ...
- android内部培训视频_第一节
声明:本视频为公司内部做android培训时录制的,无任何商业目的.同时鉴于水平有限,可能不符合您的需求,放在这里的目的是提供给公司同事下载,作为培训的一个记录,也作为一个系列教程的自我督促完成的理由 ...
- 第二篇:呈现内容_第三节:CompositeControl呈现
一.CompositeControl的呈现过程 CompositeControl派生自WebControls,重写了Render(HtmlTextWriter writer)方法.在调用基类WebCo ...
- 第一篇:初识ASP.NET控件开发_第一节:控件类及其继承关系
1)System.Web.UI.Control(以下简称Control) Control 类是包括自定义控件.用户控件和页在内的所有 ASP.NET 服务器控件的基类..定义由所有 ASP.NET 服 ...
- 第二篇 dom内容操作之value
一.内容操作的三种方式 . 详情看第一篇 innerText innerHtml . value ==>表单类的标签 input >text passwd textarea . check ...
- Vue快速学习_第一节
之前写CRM都是Django前后端一起写的,在大部分项目中实际上前后端是分离的,因此我们需要学习一个前端框架来进行前端页面的编写,这里选择了Vue进行学习,好了开始学习吧. 1.ES6部分知识点学习 ...
- 第二篇 Fiddler配置_浏览器&手机
什么是Fiddler? 网络项目的开发和测试中,Fiddler是强大的抓包工具,它的原理是以web代理服务器的形式进行工作的 ,可以说是非常常用的手头工具了,本文就Fiddler使用和配置进行说明. ...
- 第二部分 实习操作课程 第一节 ArcGIS Online的基本功能
随机推荐
- bash if 表达式含义
[ -a FILE ] 如果 FILE 存在则为真. [ -b FILE ] 如果 FILE 存在且是一个块特殊文件则为真. [ -c FILE ] 如果 FILE 存在且是一个字特殊文件则为真. [ ...
- vue $options 获取自定义属性
说明: https://cn.vuejs.org/v2/api/#vm-options 用于当前 Vue 实例的初始化选项.需要在选项中包含自定义属性时会有用处. element-ui代码中经常定义组 ...
- UVALive - 4618 Wormholes(负环)
题目大意:给出出发点和终点和m个虫洞(虫洞的出发点.终点,生成时间和花费时间).问从起点到终点花费的最小时间 解题思路:关键是有负环,所以直接跑最短路算法的话会TLE.所以负环要处理一下 可是这个负环 ...
- android JNI调用(Android Studio 3.0.1)(转)
最近回头复习了一下android 的jni调用,却发现按以前的方法调用失败,一怒之下就重新摸索,碰了几次壁,发现网上好多教程都不能成功调用,于是记录一下现在AS版本成功好用的调用方法. 这里设定你的n ...
- 下拉列表框select
下拉列表框select CreateTime--2017年5月15日15:39:24 Author:Marydon 三.下拉列表框 (一)语法 <select></select& ...
- ADAMS绳索仿真
在实际生活中有大量的绳索类传动运动形式.绳索类部件看似简单,但是用计算机软件对其模拟时却存在较大障碍.以钢丝绳为例,通常都是通过细长的钢丝螺旋缠绕在一起形成,在工作时当施加拉力载荷于其上,除了材料自身 ...
- 适配新路由3(D2)的LEDE/OpenWrt固件
使用MediaTek系列的芯片方案 Y1(R6830): MT7620A + MT7612EN(5G 866M) + winbond 25Q128FVFG + winbond W971GG6KB-25 ...
- 【php正则】php正则匹配UTF-8格式的中文汉字 和 【,】【,】【。】等符号
1.php正则匹配UTF-8格式的中文汉字 和 [,][,][.]等符号 if (preg_match_all("/([\x{4e00}-\x{9fa5}]+((,)?)+((,)?)+(( ...
- jquery.uploadify 在firefox会出现httperror
原来是因为我的上传处理页面的page 继承了一个基类影响到的 然后这个基类 好像是因为在别的项目里面的原因 希望对也遇到这样的问题的人有帮助咯
- (原)ubuntu挂载及开机自动挂载网络端的文件夹的方法
转载请注明出处: http://www.cnblogs.com/darkknightzh/p/7160792.html 参考网址: http://blog.csdn.net/tlight/articl ...