第二篇:呈现内容_第三节: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 ...
随机推荐
- asp.net正则表达式类的定义
using System; using System.Collections; using System.Reflection; using System.Reflection.Emit; using ...
- Kafka部署与代码实例(转)
来自:http://doc.okbase.net/QING____/archive/19447.html 也可参考: http://blog.csdn.net/21aspnet/article/det ...
- 測试AtomicInteger与普通int值在多线程下的递增操作
日期: 2014年6月10日 作者: 铁锚 Java针对多线程下的数值安全计数器设计了一些类,这些类叫做原子类,当中一部分例如以下: java.util.concurrent.atomic.Atomi ...
- ODI Studio拓扑结构的创建与配置(MySQL)
拓扑结构的创建与配置 一.概念解释 Topology Manager主要用来管理下面5类任务,并将信息存储在主资料库中,供所有模块共享使用. 物理体系结构: 定义各种技术及其数据服务器.物理架构.物理 ...
- 〖Linux〗Kubuntu设置打开应用时就只在打开时的工作区显示
有没有遇到一种情况: 在工作区1打开了应用程序Google Chrome: 这个时间感觉它打开速度比较慢,就快捷键切换到工作区2了: 结果这个时候,Google Chrome就直接在工作区2打开,多不 ...
- 面向对象高级——Object类、包装类以及匿名内部类
Object类 知识点:掌握Object类的作用.掌握Object类中toString().equal()方法的作用 ,掌握Object接收引用数据类型的操作. 假设一个类在定义时没有明白指明继承哪 ...
- V-rep学习笔记:Reflexxes Motion Library 1
V-REP中集成了在线运动轨迹生成库Reflexxes Motion Library Type IV,目前Reflexxes公司已经被谷歌收购.(The Reflexxes Motion Librar ...
- JAVA内存模型及垃圾回收自我总结
本文为原创,根据<深入理解java虚拟机>和自己的一些理解进行整理,单纯和看其他人的博客感觉不如自己一点点的画和记录来的印象深刻. JAVA内存模型: 上图中:局部变量表所需的内存在编译期 ...
- java第四节 类的继承/抽象/接口/多态性
/* 类的继承 类的继承可以简化类的定义 java只支持单继承,不允许多重继承 可以有多层继承,即一个类可以继承其一个类的子类,如类B继承了类A,类C又可以继承类B 那么类C也间接继承了类A 子类继承 ...
- 删数问题(NOI94)
删数问题(NOI94) 输入一个高精度的正整数N,去掉其中任意S个数字后剩下的数字按原左右次序组成一个新的正整数.编程对给定的N和S,寻找一种方案使得剩下的数字组成的新数最小.输出新的正整数.(N不超 ...