第二篇:呈现内容_第二节:WebControl呈现
一、WebControl的呈现过程
WebControl派生自Control类,所以WebControl的呈现功能基于Control的呈现逻辑之上,但有了比较大的扩展。
首先,WebControl重写了Render(HtmlTextWriter writer)方法,将呈现的逻辑一分为三:RenderBeginTag()、RenderContents()、RenderEndTag()。WebControl的这种设计基于一种假设:每个WebControl最终生成一个HTML控件(当然这个HTML控件中可能还包含其他HTML子控件),所以WebControl的呈现过程就可分为:呈现开始标签、呈现标签中的内容和呈现结尾标签。
protected internal override void Render(HtmlTextWriter writer)
{
this.RenderBeginTag(writer);
this.RenderContents(writer);
this.RenderEndTag(writer);
}
①呈现开始标签:
public virtual void RenderBeginTag(HtmlTextWriter writer)
{
this.AddAttributesToRender(writer);
HtmlTextWriterTag htmlTextWriterTag = this.TagKey;
if (htmlTextWriterTag != HtmlTextWriterTag.Unknown)
{
writer.RenderBeginTag(htmlTextWriterTag);
return;
}
writer.RenderBeginTag(this.TagName);
}
由上面的实现代码可知:RenderBeginTag()方法所生成的HTML标签是由WebControl.TagKey或WebControl.TagName属性决定的。
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
protected virtual HtmlTextWriterTag TagKey
{
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
get
{
return this.tagKey;
}
}
TagKey的类型为HtmlTextWriterTag 枚举,如果你的标签不在这个枚举中,则你需要把TagKey属性设为Unkown,并设置TagName属性,TagName属性为String类型,这意味着你可以将该属性设为任意值。
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
protected virtual string TagName
{
get
{
if (this.tagName == null && this.TagKey != HtmlTextWriterTag.Unknown)
{
this.tagName = Enum.Format(typeof(HtmlTextWriterTag), this.TagKey, "G").ToLower(CultureInfo.InvariantCulture);
}
return this.tagName;
}
}
- 注意:在通常情况下,我们不重写RenderBeginTag()方法,而通过重写TagKey或TagName属性来实现对生成的外围HTML标签的控制。
②呈现标签中的内容:
protected internal virtual void RenderContents(HtmlTextWriter writer)
{
base.Render(writer);
}
③呈现结尾标签:
public virtual void RenderEndTag(HtmlTextWriter writer)
{
writer.RenderEndTag();
}
到这里WebControl的呈现过程,都说完了,但有一个疑问是:最外围的HTML标签是怎么添加属性和样式属性的呢?
相信细心的同学一定发现在WebControl类RenderBeginTag()方法中第一行代码:
this.AddAttributesToRender(writer);
故名思议就是添加属性到呈现内容,我们看下该方法的实现:
protected virtual void AddAttributesToRender(HtmlTextWriter writer)
{
if (this.ID != null)
{
writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);
}
if (this._webControlFlags[4])
{
string accessKey = this.AccessKey;
if (accessKey.Length > 0)
{
writer.AddAttribute(HtmlTextWriterAttribute.Accesskey, accessKey);
}
}
if (!this.Enabled)
{
if (this.SupportsDisabledAttribute)
{
writer.AddAttribute(HtmlTextWriterAttribute.Disabled, "disabled");
}
if (this.RenderingCompatibility >= VersionUtil.Framework40 && !string.IsNullOrEmpty(WebControl.DisabledCssClass))
{
if (string.IsNullOrEmpty(this.CssClass))
{
this.ControlStyle.CssClass = WebControl.DisabledCssClass;
}
else
{
this.ControlStyle.CssClass = WebControl.DisabledCssClass + " " + this.CssClass;
}
}
}
if (this._webControlFlags[16])
{
int tabIndex = (int)this.TabIndex;
if (tabIndex != 0)
{
writer.AddAttribute(HtmlTextWriterAttribute.Tabindex, tabIndex.ToString(NumberFormatInfo.InvariantInfo));
}
}
if (this._webControlFlags[8])
{
string toolTip = this.ToolTip;
if (toolTip.Length > 0)
{
writer.AddAttribute(HtmlTextWriterAttribute.Title, toolTip);
}
}
if (this.TagKey == HtmlTextWriterTag.Span || this.TagKey == HtmlTextWriterTag.A)
{
this.AddDisplayInlineBlockIfNeeded(writer);
}
if (this.ControlStyleCreated && !this.ControlStyle.IsEmpty)
{
this.ControlStyle.AddAttributesToRender(writer, this);
}
if (this.attrState != null)
{
AttributeCollection attributes = this.Attributes;
IEnumerator enumerator = attributes.Keys.GetEnumerator();
while (enumerator.MoveNext())
{
string text = (string)enumerator.Current;
writer.AddAttribute(text, attributes[text]);
}
}
}
首先,AddAttributesToRender()是一个虚方法,我们可以重写,又因为它在RenderBeginTag()开始时被调用,很显然我们可以将最外围的HTML标签添加属性和样式属性的逻辑在这里实现。其次,我们注意到WebControl类实现RenderBeginTag()方法时完成了(例如:Enabled与否,不同呈现)等基本的功能。所以在我们重写该方法为外围标签添加自定义属性和样式属性时,为了获得WebControl提供的基本功能。需在派生的控件类中调用父类的该方法:
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
base.AddAttributesToRender(writer);
//......添加所需属性和样式的代码
}
二、从WebControl类派生"相册"控件
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace CustomServerControls
{
public class Albumn : WebControl
{
//(一):WebControl默认TagKey为span,这里重写为Div
protected override HtmlTextWriterTag TagKey
{
get
{
return HtmlTextWriterTag.Div;
}
}
//(二:)为主标签(Div)添加一些样式属性
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
base.AddAttributesToRender(writer);
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");
}
//(三):主标签的内容项是一个Img标签
protected override void RenderContents(HtmlTextWriter writer)
{
writer.AddAttribute(HtmlTextWriterAttribute.Src, "Images/nature.jpg");
writer.AddAttribute(HtmlTextWriterAttribute.Width, "160px");
writer.AddAttribute(HtmlTextWriterAttribute.Height,"160px");
writer.AddStyleAttribute(HtmlTextWriterStyle.BorderStyle, "none");
writer.AddStyleAttribute(HtmlTextWriterStyle.Padding, "0px");
writer.AddStyleAttribute(HtmlTextWriterStyle.MarginTop, "16px");
writer.RenderBeginTag(HtmlTextWriterTag.Img);
writer.RenderEndTag();
}
}
}
第二篇:呈现内容_第二节:WebControl呈现的更多相关文章
- 第二篇:呈现内容_第一节:Control呈现
一.Control的呈现过程 在上个章节““生死有序”的控件生命周期”中,我们提到Render是控件开发的主角,但在控件树的“合成模式(Composite)”部分这位主角却缺席了(戏份太多的缘由).哦 ...
- 第二篇:呈现内容_第三节:CompositeControl呈现
一.CompositeControl的呈现过程 CompositeControl派生自WebControls,重写了Render(HtmlTextWriter writer)方法.在调用基类WebCo ...
- 第二篇 dom内容操作之value
一.内容操作的三种方式 . 详情看第一篇 innerText innerHtml . value ==>表单类的标签 input >text passwd textarea . check ...
- 第二篇 Fiddler配置_浏览器&手机
什么是Fiddler? 网络项目的开发和测试中,Fiddler是强大的抓包工具,它的原理是以web代理服务器的形式进行工作的 ,可以说是非常常用的手头工具了,本文就Fiddler使用和配置进行说明. ...
- Egret入门学习日记 --- 第二篇 (书籍的选择 && 书籍目录 && 书中 3.3 节 内容)
第二篇 (书籍的选择 && 书籍目录 && 书中 3.3 节 内容) 既然选好了Egret,那我就要想想怎么学了. 开始第一步,先加个Q群先,这不,拿到了一本<E ...
- 【开源.NET】 轻量级内容管理框架Grissom.CMS(第二篇前后端交互数据结构分析)
这是 CMS 框架系列文章的第二篇,第一篇开源了该框架的代码和简要介绍了框架的目的.作用和思想,这篇主要解析如何把sql 转成标准 xml 配置文件和把前端post的增删改数据规范成方便后台解析的结构 ...
- Matlab高级教程_第二篇:MATLAB和C#一些常用的矩阵运算方法的转换
1.相关方法已经生产引用,直接调用的结果如下: 2. 相关调用代码如下: using System; using System.Collections.Generic; using System.Li ...
- Python开发【第二篇】:初识Python
Python开发[第二篇]:初识Python Python简介 Python前世今生 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏 ...
- 第二篇 Replication:分发服务器的作用
本篇文章是SQL Server Replication系列的第二篇,详细内容请参考原文. 分发服务器是SQL Server复制的核心组件.分发服务器控制并执行数据从一个服务器移动到另一个服务器的进程. ...
随机推荐
- css样式小技巧
1.css样式小技巧 HTML怎样设定使背景图片不随页面滚动而滚动 background-attachment:fixed; 2.实现li a 超过长度内容出现省略号… overflow:hidden ...
- To LACP or not to LACP (on a 5.1 vDS)
http://www.poppingclouds.com/2012/12/20/to-lacp-or-not-to-lacp-on-a-5-1-vds-2/ I have been recently ...
- Spark的运行模式(2)--Yarn-Cluster和Yarn-Client
3. Yarn-Cluster Yarn是一种统一资源管理机制,可以在上面运行多种计算框架.Spark on Yarn模式分为两种:Yarn-Cluster和Yarn-Client,前者Driver运 ...
- django之创建第3个项目:编写第一个模板文件
1.django结构 2.在站点blog下创建templates文件夹,专门用于存放模板文件 3.在templates文件夹下创建index.html文件 #index.html <!DOCTY ...
- java 怎么打印变量
//Test.java public class Test16{ public static void main(String args[]){ int age=28; System.out.prin ...
- codevs 1862 最长公共子序列(求最长公共子序列长度并统计最长公共子序列的个数)
题目描述 Description 字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x0,x1,…,xm-1”,序列Y ...
- Ubuntu与Windows7双系统下, 系统时间不一致的问题
Ubuntu使用的UTC时间, 而Windows使用的是Local Time, 就导致每次切换系统后, Windows时间都会正好晚8个小时. 有两种解决办法, 一个是修改Ubuntu, 另一个是修改 ...
- 生命周期方法调用,以及在onStop()方法中处理草稿信息
生命周期方法调用顺序 1. 从会话列表界面跳转到信息列表界面. 07-17 17:29:18.718: I/txrjsms(19370): MessageListActivity.onCreate 0 ...
- Java概述与开发环境
1.Java语言既是编译又是解释型的特点 Java没有设计成编译型语言,因为编译型语言效率高, 但可移植性差. Java也没有设计成纯解释型的语言, 因为解释型效率太低. 编译成class文件, 解释 ...
- 不让复制是不可能的----js获取选中文字
在360百科.知乎上经常会遇见禁止复制文本的情形,这能挡住一部分人复制,却挡不住程序员的复制. HTML都给我了,难道一小段文本我都拿不下来吗? F12打开控制台,然后选中文本,在控制台下粘贴以下代码 ...