第二篇:呈现内容_第三节:CompositeControl呈现
一、CompositeControl的呈现过程

CompositeControl派生自WebControls,重写了Render(HtmlTextWriter writer)方法。在调用基类WebControl的Render(HtmlTextWriter writer)方法前,先调用了EnsureChildControls()方法,以确保创建子控件。
protected internal override void Render(HtmlTextWriter writer)
{
if (base.DesignMode)
{
this.EnsureChildControls();
}
base.Render(writer);
}
①EnsureChildControls方法
该方法用于确定服务器控件是否创建了子控件或子控件是否在创建中。如果未创建子控件且子控件不在创建中,则创建子控件。该方法首先检查ChildControlsCreated属性的当前值。如果此值为false,则调用CreateChildControls方法。当需要确保已创建子控件时,将调用该方法。大多数情况下,自定义服务器控件的开发人员无须重写此方法。CompositeControl类继承自Control类的EnsureChildControls()方法源代码如下:
// System.Web.UI.Control
protected virtual void EnsureChildControls()
{
if (!this.ChildControlsCreated && !this.flags[256])
{
this.flags.Set(256);
try
{
this.ResolveAdapter();
if (this.AdapterInternal != null)
{
this.AdapterInternal.CreateChildControls();
}
else
{
this.CreateChildControls();
}
this.ChildControlsCreated = true;
}
finally
{
this.flags.Clear(256);
}
}
}
private const int creatingControls = 256; //Control类中定义的私有常量
② ChildControlsCreated属性
该属性的数据类型为bool,其用于获取一个值,该值指示是否已创建服务器控件的子控件。如果已创建子控件则该属性为true;否则为false。该属性主要是为了避免CreateChildControls方法重复创建控件。
// System.Web.UI.Control
protected bool ChildControlsCreated
{
get
{
return this.flags[8];
}
set
{
if (!value && this.flags[8])
{
this.Controls.Clear();
}
if (value)
{
this.flags.Set(8);
return;
}
this.flags.Clear(8);
}
}
③ CreateChildControls方法
重写从Control继承的受保护的CreateChildControls方法,以创建子控件的实例,并将它们添加到Controls集合,此方法可能会在页面和控件的生命周期内反复调用。为避免控件重复,ChildControlsCreated属性通常被设置为true。如果此属性返回true,则不再调用CreateChildControls方法。
// System.Web.UI.Control
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
protected internal virtual void CreateChildControls()
{
}
二、从CompositeControl类派生"非空"文本控件
实现代码:
[ToolboxData("<{0}:NonEmptyBox runat=server></{0}:NonEmptyBox>")]
public class NonEmptyBox : CompositeControl
{
private Label _lbInput;
private TextBox _txtInput;
private RequiredFieldValidator _rfvInput; //非空验证
protected override void CreateChildControls()
{
this.Controls.Clear();
_lbInput = new Label();
_lbInput.ID = "lbInput";
_lbInput.Text = this.LabelText;
_txtInput = new TextBox();
_txtInput.ID = "txtInput";
_rfvInput = new RequiredFieldValidator();
_rfvInput.ID = "rfvInput";
_rfvInput.ErrorMessage = string.Format("{0}不能为空!",_lbInput.Text);
_rfvInput.Text = "*";
_rfvInput.Display = ValidatorDisplay.Dynamic;
_lbInput.AssociatedControlID = _lbInput.ID;
_rfvInput.ControlToValidate = _txtInput.ID;
this.Controls.Add(_lbInput);
this.Controls.Add(_txtInput);
this.Controls.Add(_rfvInput);
this.ChildControlsCreated = true;
}
public string LabelText
{
get
{
string labelText = (string)this.ViewState["LabelText"];
if (labelText != null)
{
return labelText;
}
return string.Empty;
}
set
{
this.ViewState["LabelText"] = value;
}
}
}
测试代码:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="NonEmptyBoxTest.aspx.cs" Inherits="CustomServerControlTest.NonEmptyBoxTest" %>
<%@ Register assembly="CustomServerControl" namespace="CustomServerControl" tagprefix="csc" %>
<!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 runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<csc:NonEmptyBox ID="NonEmptyBox1" runat="server" LabelText="姓名:" />
<csc:NonEmptyBox ID="NonEmptyBox2" runat="server" LabelText="住址:" />
<asp:Button ID="Button1" runat="server" Text=" 提 交 " />
<asp:ValidationSummary ID="ValidationSummary1" runat="server" />
</div>
</form>
</body>
</html>
测试截图:


NonEmptyBox 控件呈现的HTML:
<span id="NonEmptyBox1">
<label for="NonEmptyBox1_lbInput" id="NonEmptyBox1_lbInput">姓名:</label>
<input name="NonEmptyBox1$txtInput" type="text" id="NonEmptyBox1_txtInput" />
<span id="NonEmptyBox1_rfvInput" style="color: Red; display: none;">*</span>
</span>
三、从CompositeControl类派生"邮箱地址"输入控件
实现代码:
[ToolboxData("<{0}:EmailInput runat=server></{0}:EmailInput>")]
public class EmailInput : CompositeControl
{
private TextBox _txtEmail;
private RequiredFieldValidator _rfvEmail; //非空验证
private RegularExpressionValidator _revEmail; //格式验证
protected override void CreateChildControls()
{
this.Controls.Clear();
_txtEmail = new TextBox();
_txtEmail.ID = "txtEmail";
_rfvEmail = new RequiredFieldValidator();
_rfvEmail.ID = "rfvEmail";
_rfvEmail.ErrorMessage = "请输入邮箱地址!";
_rfvEmail.Text = "*";
_rfvEmail.Display = ValidatorDisplay.Dynamic;
_rfvEmail.ControlToValidate = _txtEmail.ID;
_revEmail = new RegularExpressionValidator();
_revEmail.ID = "revEmail";
_revEmail.ErrorMessage = "邮件格式错误!";
_revEmail.Text = "*";
_revEmail.Display = ValidatorDisplay.Dynamic;
_revEmail.ValidationExpression = @"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*";
_revEmail.ControlToValidate = _txtEmail.ID;
this.Controls.Add(_txtEmail);
this.Controls.Add(_rfvEmail);
this.Controls.Add(_revEmail);
this.ChildControlsCreated = true; //在CreateChildControls()方法的最后把ChildControlsCreated设为true,这样就实现了既保证组合控件的子控件得以创建,又不会重复调用创建子控件的过程。
}
protected override HtmlTextWriterTag TagKey
{
get
{
return HtmlTextWriterTag.Table;
}
}
protected override void RenderContents(HtmlTextWriter writer)
{
if (base.DesignMode)
{
this.EnsureChildControls(); //对于组合控件来说,最好在访问它的子控件之前添加对EnsureChildControls()的调用,避免在设计时遭遇空引用异常。
}
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.AddAttribute(HtmlTextWriterAttribute.Align, "left");
writer.AddAttribute(HtmlTextWriterAttribute.Width, "80px");
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.Write("Email:");
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Td);
_txtEmail.RenderControl(writer);
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Td);
_rfvEmail.RenderControl(writer);
_revEmail.RenderControl(writer);
writer.RenderEndTag();
writer.RenderEndTag();
}
}
测试代码:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="EmailInputTest.aspx.cs" Inherits="CustomServerControlTest.EmailInputTest" %>
<%@ Register Assembly="CustomServerControl" Namespace="CustomServerControl" TagPrefix="csc" %>
<!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 runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<csc:EmailInput ID="EmailInput1" runat="server" />
<asp:Button ID="Button1" runat="server" Text=" 提 交 " />
<asp:ValidationSummary ID="ValidationSummary1" runat="server" />
</div>
</form>
</body>
</html>
测试截图:



EmailInput 控件呈现的HTML:
<table id="EmailInput1">
<tr>
<td align="left" width="80px">
Email:
</td>
<td>
<input name="EmailInput1$txtEmail" type="text" id="EmailInput1_txtEmail" />
</td>
<td>
<span id="EmailInput1_rfvEmail" style="color: Red; display: none;">*</span>
<span id="EmailInput1_revEmail" style="color: Red; display: none;">*</span>
</td>
</tr>
</table>
第二篇:呈现内容_第三节:CompositeControl呈现的更多相关文章
- 第二篇:呈现内容_第二节:WebControl呈现
一.WebControl的呈现过程 WebControl派生自Control类,所以WebControl的呈现功能基于Control的呈现逻辑之上,但有了比较大的扩展. 首先,WebControl重写 ...
- 第二篇:呈现内容_第一节:Control呈现
一.Control的呈现过程 在上个章节““生死有序”的控件生命周期”中,我们提到Render是控件开发的主角,但在控件树的“合成模式(Composite)”部分这位主角却缺席了(戏份太多的缘由).哦 ...
- 第二篇 dom内容操作之value
一.内容操作的三种方式 . 详情看第一篇 innerText innerHtml . value ==>表单类的标签 input >text passwd textarea . check ...
- 第二篇 Fiddler配置_浏览器&手机
什么是Fiddler? 网络项目的开发和测试中,Fiddler是强大的抓包工具,它的原理是以web代理服务器的形式进行工作的 ,可以说是非常常用的手头工具了,本文就Fiddler使用和配置进行说明. ...
- 【开源.NET】 轻量级内容管理框架Grissom.CMS(第二篇前后端交互数据结构分析)
这是 CMS 框架系列文章的第二篇,第一篇开源了该框架的代码和简要介绍了框架的目的.作用和思想,这篇主要解析如何把sql 转成标准 xml 配置文件和把前端post的增删改数据规范成方便后台解析的结构 ...
- Egret入门学习日记 --- 第二篇 (书籍的选择 && 书籍目录 && 书中 3.3 节 内容)
第二篇 (书籍的选择 && 书籍目录 && 书中 3.3 节 内容) 既然选好了Egret,那我就要想想怎么学了. 开始第一步,先加个Q群先,这不,拿到了一本<E ...
- 隐藏内容_网络推广_seo中级视频教程详解
课程背景:SEO(Search Engine Optimization),汉译为搜索引擎优化.搜索引擎优化是一种利用搜索引擎的搜索规则来提高目的网站在有关搜索引擎内的排名的方式.SEO目的理解是:为网 ...
- ASP.NET自定义控件组件开发 第一章 第二篇 接着待续
原文:ASP.NET自定义控件组件开发 第一章 第二篇 接着待续 ASP.NET自定义控件组件开发 第一章 第二篇 接着待续 很感谢大家给我的第一篇ASP.NET控件开发的支持!在写这些之前,我也看了 ...
- jquery jtemplates.js模板渲染引擎的详细用法第二篇
jquery jtemplates.js模板渲染引擎的详细用法第二篇 关于jtemplates.js的用法在第一篇中已经讲过了,这里就直接上代码,不同之处是绑定模板的方式,这里讲模板的数据专门写一个t ...
随机推荐
- javascript数组操作大全,数组方法总汇
1. shift:删除原数组第一项,并返回删除元素的值:如果数组为空则返回undefined var a = [1,2,3,4,5]; var b = a.shift(); //a:[2,3,4,5] ...
- 微信 js api[转]
rainbow661314 微信api /**! * 微信内置浏览器的Javascript API,功能包括: * * 1.分享到微信朋友圈 * 2.分享给微信好友 * 3.分享到腾讯微博 * 4.新 ...
- POSTGRESQL 查看数据库 数据表大小
1.查看数据库大小: select pg_database_size('log_analysis'); select pg_database_size('log_analysis'); pg_data ...
- HDU 3001 Travelling (三进制状态压缩 DP)
题意:有 n 个city,能够选择任一城市作为起点,每一个城市不能訪问超过2次, 城市之间有权值,问訪问所有n个城市须要的最小权值. 思路:由于每一个城市能够訪问最多两次,所以用三进制表示訪问的状态. ...
- mybatis批量删除(逻辑删除)
在Mapper.xml文件中 <!-- 批量删除 --> <delete id="deleteAd" parameterType="java.util. ...
- tpcc-mysql 系列一:安装使用
1:安装epel包: rpm -Uvh http://dl.fedoraproject.org/pub/epel/5/i386/epel-release-5-4.noarch.rpm 2: yum i ...
- Knockout学习之组合监控属性
组合监控属性 顾名思义,就是我们可以将多个属性合并为一个属性.这样在显示的时候就是整体了,并且其中任何一个属性发生改变,这个属性也都会随之发生改变从而更新视图,而这些只需要使用computed函数就可 ...
- Dlib三维点云示例
Dlib三维点云示例 源代码来自Dlib的示例代码http://dlib.net/3d_point_cloud_ex.cpp.html 在windows下需要链接winmm``comctl32``gd ...
- 图解Win7如何手动添加受信任证书
点击开始—>运行,如下图所示: 弹出“控制台”窗口如下,如下图所示: 点击“文件—添加/删除管理单元”,如下图所示: 选择“证书”,并点击“添加”,如下图所示: 在弹出的窗口上选 ...
- jenkins关闭和重启
我们用jar -jar jenkins.war来启动jenkins服务器,那么我们如何关闭或者重启jenkins服务器呢?经过搜索找到了相应的方法. 关闭jenkins服务 只需要在访问jenkins ...