第二篇:呈现内容_第三节: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呈现相关推荐
- 第二篇:呈现内容_第四节:个性化自定义控件
一.特性(Attribute): ①DefaultProperty:(例:[DefaultProperty("Text")]) DefaultProperty是用于设置控件的默认属 ...
- TLS协议学习-第二篇-握手协议
TLS协议学习第二篇,内容来自:https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-200 ...
- B站黑马测试第二篇P206视频数据库SQL语句‘关联查询_数据准备‘代码
drop table if exists category; create table category( id int unsigned primary key auto_increment, ty ...
- Go实现Raft第二篇:选举
女主宣言 今天小编为大家分享一篇关于Golang实现Raft的文章,本篇文章为系列中的第二篇,对Raft中的选举机制进行介绍并使用go进行实现.希望能对大家有所帮助. PS:丰富的一线技术.多元化的表 ...
- ASP.NET自定义控件组件开发 第一章 第二篇 接着待续
ASP.NET自定义控件组件开发 第一章 第二篇 接着待续 ASP.NET自定义控件组件开发 第一章 第二篇 接着待续 很感谢大家给我的第一篇ASP.NET控件开发的支持!在写这些之前,我也看了一些例 ...
- Python之路【第二篇】:Python基础(一)
Python之路[第二篇]:Python基础(一) 入门知识拾遗 一.作用域 对于变量的作用域,执行声明并在内存中存在,该变量就可以在下面的代码中使用. 1 2 3 if 1==1: name ...
- 使用 ASP.NET Core, Entity Framework Core 和 ABP 创建N层Web应用 第二篇
介绍 这是"使用 ASP.NET Core ,Entity Framework Core 和 ASP.NET Boilerplate 创建N层 Web 应用"系列文章的第二篇.以下 ...
- Android 进阶第二篇——性能优化
Android 进阶第二篇--性能优化 一些Android书籍喜欢把性能优化放在最后的章节,简单提一提作为内容全面的点缀.在这里我将工具使用和性能优化的一些个人经验放在进阶系列博客的开始,因为我认为防 ...
- SQLSERVER是怎麽通过索引和统计信息来找到目标数据的(第二篇)
SQLSERVER是怎麽通过索引和统计信息来找到目标数据的(第二篇) 在看这篇文章的内容之前,请阁下先看第一篇的内容,因为没有第一篇的基础的话会看到一头雾水哦o(∩_∩)o 第一篇的地址:SQLSER ...
- U3D_Shader编程(第二篇:基础夯实篇)
<U3D_Shader编程> ##<U3D_Shader编程>发布说明: ++++Shader一个高大上的领域,不管怎么样,我来了. ++++立钻哥哥从2018年开始正式对Sh ...
最新文章
- SQL2008R2 express版本不支持维护计划
- 64位oracle客户端_开发小记-golang连接Oracle数据库配置
- swift学习之set和get方法
- 111. 畜栏预定【贪心】
- PowerShell学习笔记(1)-基础
- Activiti实战. 1.5Activiti架构与组件
- 修改Git提交者昵称和邮箱
- 上传文件input(type=file)美化。
- 【机器学习】数据挖掘算法——关联规则(三),FP-growth算法
- make zImage和make uImage的区别和mkimage工具的使用
- [置顶] java除0问题探究
- geek软件是干什么的_详解强力卸载软件Geek Uninstaller使用教程
- Asp.Net MVC部暑托管服务器iis7提示403错误解决方法
- Zend Studio配置:使用PHP 7进行开发
- Digital Overdose 2021 Autumn CTF 部分题目赛后复现
- 《人人都在说谎:赤裸裸的数据真相》读书笔记1
- ICCV 2021 | Transformer结合自监督学习!Facebook开源DINO
- python locust在windows下的安装
- 看了他家的红木装修,彻底被圈粉了,庄重典雅又复古舒适
- linux 命令行 迅雷替代,Mac/Linux下迅雷替代方案
热门文章
- 计算机组成原理第一部: 计算机发展到加法器ALU的改进
- Linux: ubuntu Appium连接手机
- chrome浏览器打开网页排版错乱
- 16、Android -- ListView 基础学习
- 编写算法将二叉树中所有结点的左、右子树相互交换
- android_基础_修改系统背景(状态栏颜色、导航栏颜色、标题栏颜色等等)
- 信息安全审计系统S-Audit
- 游戏公司的区块链冒险:一周时间从火爆到熄火
- Hex Fiend——mac 下 WinHex的完美替代
- 红帽子Linux7安装Oracle,RedHat Enterprise Linux7.0安装Oracle 12C