第二篇:呈现内容_第三节: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 ...
随机推荐
- Linux下使用Nohup后台运行程序
一.不输出日志的命令 #!/bin/bash echo "starting nohup..." nohup dotnet ./mynetcoreapp.dll > /dev/ ...
- 方法(method)和函数(function)有什么区别?
方法(method)和函数(function)有什么区别? 定义和参数区别 函数是独立的功能,与对象无关,需要显示的传递数据 方法与对象和类相关,依赖对象而调用,可以直接处理对象上的数据,也就是隐式传 ...
- notepad++一键运行python
打开notepad++,找到菜单栏的run菜单. 子菜单选中run 弹出的小窗口中,输入cmd /k python "$(FULL_CURRENT_PATH)" & ...
- MySQL 内存和CPU优化相关的参数
mysql> SHOW GLOBAL STATUS LIKE 'innodb%read%'; +---------------------------------------+--------- ...
- 一个简单的ExtJS搜索建议框
封装的是一个Ext4.2的组件,继承并兼容于Ext的ComboBox. 实现原理非常easy,在 combo 中监听 keyup 事件就可以. 搜索建议的Combo.基本上全然兼容, 使用方式与Com ...
- RHEL7 在不同的环境中使用不同的网络配置文件
比如,我们可以设置RHEL7 系统在公司时使用一个网卡配置文件:在家时则使用另外一个配置文件(可以根据不同的环境设置多个网卡配置文件). 网卡配置信息如下: [root@rhel7 ~]# nmcli ...
- ACE的源码划分
前几篇文章也提到过,ACE的所有源文件和头文件都杂乱堆在了ACE_wrappers/ace目录下.这样的代码组织方式给学习ACE带来了很大的困难,很多朋友在看到ace目录下庞大的代码的时候,几乎就失去 ...
- springboot自定义jdbc操作库+基于注解切点AOP
发布时间:2018-11-08 技术:springboot+aop 概述 springBoot集成了自定义的jdbc操作类及AOP,因为spring自带的JdbcTemplate在实际项目中并 ...
- TL Cop
第一讲 研发技术型人才的特点 一.为何要重视技术与研发技术管理 1.中国技术型企业近十年的发展路线图以及经验教训 2.技术还是营销:中国企业的痛 3.名家论技术与研发技术管理 二.研发技术人才的特点 ...
- highstock禁用UTC
xAxis: { labels: { format: '{value:%Y-%m-%d}', /* * 也可以用 formatter 格式化函数,时间格式化说明如下: * %Y 年 * %m 月 * ...