第二篇:呈现内容_第三节: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 ...
随机推荐
- 012-Go ORM框架之Gorm测试
1:参考:https://github.com/jinzhu/gorm 2:数据库脚本(pg) -- create table posts( id serial primary key, conten ...
- thinkPHP 快速上手
http://www.kancloud.cn/manual/thinkphp5/118006 克隆项目 //首先克隆下载应用项目仓库 git clone https://github.com/top- ...
- Elasticsearch cluster health: yellow unassigned shards
查看ES各个分片的状态 $ curl -XGET http://127.0.0.1:9200/_cluster/health?pretty { "cluster_name" : & ...
- 请指出document load和document ready的区别?
共同点:这两种事件都代表的是页面文档加载时触发. 异同点: ready 事件的触发,表示文档结构已经加载完成(不包含图片等非文字媒体文件). onload 事件的触发,表示页面包含图片等文件在内的所有 ...
- python在linux的报错集锦
1. 报错提示 /usr/lib/python2.7/site-packages/requests/__init__.py:80: RequestsDependencyWarning: urllib3 ...
- 〖Android〗利用droidsshd在Android手机中开启 sshd,sftp,..
源码下载地址: src: git clone https://code.google.com/p/droidsshd/ apk: http://droidsshd.googlecode.com/fil ...
- JAVA识别字符串是数字(英文)还是汉字,web页面进行字符截断的帮助类
public static void main(String[] args) { //长度是2说明是英文/数字/英文状态下的字符,长度为4说明是汉字/中文状态下的字符 String str = &qu ...
- Python-Flask实现电影系统管理后台
代码地址如下:http://www.demodashi.com/demo/14850.html 项目描述 该项目实现电影系统的后台接口,包括用户,电影,场次,订单,评论,优惠券,推荐,收藏等多个模块, ...
- HttpServer发送数据到kafka
文件夹 1.需求 2.框架结构图和步鄹图 3.代码结构 4.代码展现 ------------------------ 1.需求 1.1.解析路径,将路径的最后一个字符串作为Appkey: 1.2.数 ...
- Easyui入门视频教程 第04集---Easyui布局
目录 目录 ----------------------- Easyui入门视频教程 第09集---登录完善 图标自定义 Easyui入门视频教程 第08集---登录实现 ajax button的 ...