📄 webctrlauthoring.aspx
字号:
<%@ Register TagPrefix="Acme" Namespace="Acme" Assembly="QSTools" %>
<%@ Register TagPrefix="Acme" TagName="SourceRef" Src="/quickstart/aspplus/util/SrcRef.ascx"%>
<!-- #include virtual="/quickstart/aspplus/include/header.inc" -->
<h4>创作自定义控件</h4>
<p>
<!-- #include virtual="/quickstart/aspplus/include/wftoc7.inc" -->
<p>
<hr>
本“入门”节说明高级开发人员可以如何编写他们自己的在 ASP.NET 页框架中工作的 ASP.NET 服务器控件。通过编写自己的自定义 ASP.NET 服务器控件,可以封装可在 ASP.NET 页上重用的控件中的自定义用户界面和其他功能。“入门”通过实际操作的示例提供关于如何创作自定义控件的介绍。有关控件创作的更多信息,请参阅“Microsoft .NET 框架 SDK”文档中的“开发 ASP.NET 服务器控件”。
<p>
<b>注意:</b>本节介绍的控件虽然在运行时可以在 ASP.NET 页上正常工作,但是在设计时可能无法在窗体设计器(如 Microsoft Visual Studio .NET)中正常工作。为了能在设计器中工作,控件需要应用此处未说明的设计时属性。有关需要应用的设计时属性的详细信息,请参阅 SDK 文档中的“组件的设计时属性”。
<p>
<!--BEGIN SECTION--> <a name="simplectrl"><span class="subhead">开发简单的自定义控件</span>
<p>
开始创作您自己的 ASP.NET 服务器控件很容易。创建简单的自定义控件时,您所要做的只是定义从 <b>System.Web.UI.Control</b> 派生的类并重写它的 <b>Render</b> 方法。<b>Render</b> 方法采用 <b>System.Web.UI.HtmlTextWriter</b> 类型的参数。控件要发送到客户端的 HTML 作为字符串参数传递到 <b>HtmlTextWriter</b> 的 <b>Write</b> 方法。
<p>
下面的示例说明呈现消息字符串的简单控件。
<p>
<Acme:LangSwitch runat="server">
<CsTemplate>
<Acme:SourceRef
RunSample="/quickstart/aspplus/samples/webforms/ctrlauth/simple/CS/Simple.aspx"
ViewSource="/quickstart/aspplus/samples/webforms/ctrlauth/simple/Simple.src"
Icon="/quickstart/aspplus/images/ctrlauth1.gif"
Caption="C# Simple.aspx"
runat="server" />
</CsTemplate>
<VbTemplate>
<Acme:SourceRef
RunSample="/quickstart/aspplus/samples/webforms/ctrlauth/simple/VB/Simple.aspx"
ViewSource="/quickstart/aspplus/samples/webforms/ctrlauth/simple/Simple.src"
Icon="/quickstart/aspplus/images/ctrlauth1.gif"
Caption="VB Simple.aspx"
runat="server" />
</VbTemplate>
<JsTemplate>
<Acme:SourceRef
RunSample="/quickstart/aspplus/samples/webforms/ctrlauth/simple/JS/Simple.aspx"
ViewSource="/quickstart/aspplus/samples/webforms/ctrlauth/simple/Simple.src"
Icon="/quickstart/aspplus/images/ctrlauth1.gif"
Caption="JScript Simple.aspx"
runat="server" />
</JsTemplate>
</Acme:LangSwitch>
<!--BEGIN SECTION-->
<p>
<a name="properties"><br> <span class="subhead">定义简单属性</span>
<p>
属性类似具有访问器方法的“聪明”字段。应该从控件公开属性而不是公开公共字段,因为属性允许数据隐藏、可以版本化并受可视化设计器的支持。属性具有设置和检索属性的 get/set 访问器方法,并允许在需要时执行附加的程序逻辑。
<p>
下面的示例显示如何添加与基元数据类型(如整型、布尔型和字符串)对应的简单属性。该示例定义三个属性——<code>Message</code> 属于字符串类型,<code>MessageSize</code> 属于枚举类型,<code>Iterations</code> 属于整型类型。注意设置简单属性和枚举属性的页语法。
<p>
<Acme:LangSwitch runat="server">
<CsTemplate>
<Acme:SourceRef
RunSample="/quickstart/aspplus/samples/webforms/ctrlauth/simple/CS/SimpleProperty.aspx"
ViewSource="/quickstart/aspplus/samples/webforms/ctrlauth/simple/SimpleProperty.src"
Icon="/quickstart/aspplus/images/ctrlauth2.gif"
Caption="C# SimpleProperty.aspx"
runat="server" />
</CsTemplate>
<VbTemplate>
<Acme:SourceRef
RunSample="/quickstart/aspplus/samples/webforms/ctrlauth/simple/VB/SimpleProperty.aspx"
ViewSource="/quickstart/aspplus/samples/webforms/ctrlauth/simple/SimpleProperty.src"
Icon="/quickstart/aspplus/images/ctrlauth2.gif"
Caption="VB SimpleProperty.aspx"
runat="server" />
</VbTemplate>
<JsTemplate>
<Acme:SourceRef
RunSample="/quickstart/aspplus/samples/webforms/ctrlauth/simple/JS/SimpleProperty.aspx"
ViewSource="/quickstart/aspplus/samples/webforms/ctrlauth/simple/SimpleProperty.src"
Icon="/quickstart/aspplus/images/ctrlauth2.gif"
Caption="JScript SimpleProperty.aspx"
runat="server" />
</JsTemplate>
</Acme:LangSwitch>
<!--BEGIN SECTION-->
<p>
<a name="classprops"><br> <span class="subhead">定义类属性</span>
<p>
如果 A 类具有一个类型为 B 类的属性,则 B 的属性(如果有)称为 A 的子属性。下面的示例定义自定义控件 <code>SimpleSubProperty</code>,该控件具有 <code>Format</code> 类型的属性。<code>Format</code> 是具有两个基元属性的类——<code>Color</code> 和 <code>Size</code>,这两个属性反过来成为 <code>SimpleSubProperty</code> 的子属性。
<p>
<Acme:LangSwitch runat="server">
<CsTemplate>
<Acme:SourceRef
RunSample="/quickstart/aspplus/samples/webforms/ctrlauth/simple/CS/SimpleSubProperty.aspx"
ViewSource="/quickstart/aspplus/samples/webforms/ctrlauth/simple/SimpleSubProperty.src"
Icon="/quickstart/aspplus/images/ctrlauth3.gif"
Caption="C# SimpleSubProperty.aspx"
runat="server" />
</CsTemplate>
<VbTemplate>
<Acme:SourceRef
RunSample="/quickstart/aspplus/samples/webforms/ctrlauth/simple/VB/SimpleSubProperty.aspx"
ViewSource="/quickstart/aspplus/samples/webforms/ctrlauth/simple/SimpleSubProperty.src"
Icon="/quickstart/aspplus/images/ctrlauth3.gif"
Caption="VB SimpleSubProperty.aspx"
runat="server" />
</VbTemplate>
<JsTemplate>
<Acme:SourceRef
RunSample="/quickstart/aspplus/samples/webforms/ctrlauth/simple/JS/SimpleSubProperty.aspx"
ViewSource="/quickstart/aspplus/samples/webforms/ctrlauth/simple/SimpleSubProperty.src"
Icon="/quickstart/aspplus/images/ctrlauth3.gif"
Caption="JScript SimpleSubProperty.aspx"
runat="server" />
</JsTemplate>
</Acme:LangSwitch>
<p>
注意 ASP.NET 具有设置子属性的特殊语法。下面的代码示例显示如何以声明方式设置 <code>SimpleSubProperty</code> 上的 <code>Format.Color</code> 和 <code>Format.Size</code> 子属性。“-”语法指示子属性。
<p>
<code><SimpleControlSamples:SimpleSubProperty Message="Hello There" Format-Color="red" Format-Size="3" runat=server/></code>
<p>
<!--BEGIN SECTION-->
<p>
<a name="innercontent"><br> <span class="subhead">检索内部内容</span>
<p>
每个控件都具有从 <b>System.Web.UI.Control</b> 继承的 <b>Controls</b> 属性。这是表示控件的子控件(如果有)的集合属性。如果控件未用 <b>ParseChildrenAttribute</b> 标记,或是标记为 <b>ParseChildrenAttribute(ChildrenAsProperties = false)</b>,则当控件在页上以声明方式使用时,ASP.NET 页框架将应用以下分析逻辑。如果分析器在控件的标记内遇到嵌套控件,它将创建嵌套控件的实例并将它们添加到控件的 <b>Controls</b> 属性。标记之间的文本添加为 <b>LiteralControl</b>。任何其他嵌套元素都生成分析器错误。
<p>
下面的示例显示自定义控件 <code>SimpleInnerContent</code>。该控件通过检查是否已将 <b>LiteralControl</b> 添加到它的控件集合中,来呈现添加在其标记之间的文本。如果已添加,则它将检索 <b>LiteralControl</b> 的 <b>Text</b> 属性,并将其追加到它的输出字符串。
<p>
<Acme:LangSwitch runat="server">
<CsTemplate>
<Acme:SourceRef
RunSample="/quickstart/aspplus/samples/webforms/ctrlauth/simple/CS/SimpleInnerContent.aspx"
ViewSource="/quickstart/aspplus/samples/webforms/ctrlauth/simple/SimpleInnerContent.src"
Icon="/quickstart/aspplus/images/ctrlauth4.gif"
Caption="C# SimpleInnerContent.aspx"
runat="server" />
</CsTemplate>
<VbTemplate>
<Acme:SourceRef
RunSample="/quickstart/aspplus/samples/webforms/ctrlauth/simple/VB/SimpleInnerContent.aspx"
ViewSource="/quickstart/aspplus/samples/webforms/ctrlauth/simple/SimpleInnerContent.src"
Icon="/quickstart/aspplus/images/ctrlauth4.gif"
Caption="VB SimpleInnerContent.aspx"
runat="server" />
</VbTemplate>
<JsTemplate>
<Acme:SourceRef
RunSample="/quickstart/aspplus/samples/webforms/ctrlauth/simple/JS/SimpleInnerContent.aspx"
ViewSource="/quickstart/aspplus/samples/webforms/ctrlauth/simple/SimpleInnerContent.src"
Icon="/quickstart/aspplus/images/ctrlauth4.gif"
Caption="JScript SimpleInnerContent.aspx"
runat="server" />
</JsTemplate>
</Acme:LangSwitch>
<p>
<b>注意:</b>如果自定义控件是从 <b>WebControl</b> 派生的,它将不具有示例中描述的分析逻辑,因为 <b>WebControl</b> 是用 <b>ParseChildrenAttribute(ChildrenAsProperties = true)</b> 标记的,这导致不同的分析逻辑。有关 <b>ParseChildrenAttribute</b> 的更多信息,请参阅 SDK 文档。
<p>
<!--BEGIN SECTION-->
<p>
<a name="composition"><br> <span class="subhead">开发复合控件</span>
<p>
可以通过使用类撰写组合现有控件来创作新控件。复合控件等效于使用 ASP.NET 页语法创作的用户控件。用户控件和复合控件之间的主要差异是用户控件保持为 .ascx 文本文件,而复合控件则经过编译并保持在程序集中。
<p>
开发复合控件的主要步骤是:
<ul>
<li>重写从 <b>Control</b> 继承的受保护的 <b>CreateChildControls</b> 方法,以创建子控件的实例并将它们添加到控件集合。
<li>如果复合控件的新实例将在页上重复创建,请实现 <b>System.Web.UI.INamingContainer</b> 接口。这是不具有方法的标记接口。当用控件实现时,ASP.NET 页框架将在此控件下创建新的命名范围。这确保了子控件在控件层次结构树中具有唯一的 ID。
</ul>
因为子控件会提供呈现逻辑,所以不必重写 <b>Render</b> 方法。可以公开合成子控件属性的属性。
<p>
下面的示例定义复合控件 <code>Composition1</code>,该控件组合 <b>System.Web.UI.LiteralControl</b> 与 <b>System.Web.UI WebControls.TextBox</b>。<code>Composition1</code> 公开一个整数类型的自定义属性 <code>Value</code>,该属性映射到 <b>TextBox</b> 的 <b>Text</b> 属性。
<p>
<Acme:LangSwitch runat="server">
<CsTemplate>
<Acme:SourceRef
RunSample="/quickstart/aspplus/samples/webforms/ctrlauth/composition/CS/Composition1.aspx"
ViewSource="/quickstart/aspplus/samples/webforms/ctrlauth/composition/Composition1.src"
Icon="/quickstart/aspplus/images/ctrlauth5.gif"
Caption="C# Composition1.aspx"
runat="server" />
</CsTemplate>
<VbTemplate>
<Acme:SourceRef
RunSample="/quickstart/aspplus/samples/webforms/ctrlauth/composition/VB/Composition1.aspx"
ViewSource="/quickstart/aspplus/samples/webforms/ctrlauth/composition/Composition1.src"
Icon="/quickstart/aspplus/images/ctrlauth5.gif"
Caption="VB Composition1.aspx"
runat="server" />
</VbTemplate>
<JsTemplate>
<Acme:SourceRef
RunSample="/quickstart/aspplus/samples/webforms/ctrlauth/composition/JS/Composition1.aspx"
ViewSource="/quickstart/aspplus/samples/webforms/ctrlauth/composition/Composition1.src"
Icon="/quickstart/aspplus/images/ctrlauth5.gif"
Caption="JScript Composition1.aspx"
runat="server" />
</JsTemplate>
</Acme:LangSwitch>
<!--BEGIN SECTION-->
<p>
<a name="postbackevts"><br> <span class="subhead">在复合控件中处理事件</span>
<p>
复合控件可以处理其子控件引发的事件。这通过提供事件处理方法,并将委托附加到子控件引发的事件来完成。
<p>
下面的示例显示复合控件 <code>Composition2</code>,该控件将两个按钮控件(名为 <code>Add</code> 和 <code>Subtract</code>)添加到上一示例中的复合控件,并为按钮的 <b>Click</b> 事件提供事件处理方法。这些方法增加和减少 <code>Composition2</code> 的 <code>Value</code> 属性。<code>Composition2</code> 的 <b>CreateChildControls</b> 方法创建引用这些方法的事件处理程序(委托)的实例,并将委托附加到 <b>Button</b> 实例的 <b>Click</b> 事件。最后得到一个进行自己的事件处理的控件——单击 <code>Add</code> 按钮时,文本框中的值增加;单击 <code>Subtract</code> 按钮时,值减少。
<p>
<Acme:LangSwitch runat="server">
<CsTemplate>
<Acme:SourceRef
RunSample="/quickstart/aspplus/samples/webforms/ctrlauth/composition/CS/Composition2.aspx"
ViewSource="/quickstart/aspplus/samples/webforms/ctrlauth/composition/Composition2.src"
Icon="/quickstart/aspplus/images/ctrlauth6.gif"
Caption="C# Composition2.aspx"
runat="server" />
</CsTemplate>
<VbTemplate>
<Acme:SourceRef
RunSample="/quickstart/aspplus/samples/webforms/ctrlauth/composition/VB/Composition2.aspx"
ViewSource="/quickstart/aspplus/samples/webforms/ctrlauth/composition/Composition2.src"
Icon="/quickstart/aspplus/images/ctrlauth6.gif"
Caption="VB Composition2.aspx"
runat="server" />
</VbTemplate>
<JsTemplate>
<Acme:SourceRef
RunSample="/quickstart/aspplus/samples/webforms/ctrlauth/composition/JS/Composition2.aspx"
ViewSource="/quickstart/aspplus/samples/webforms/ctrlauth/composition/Composition2.src"
Icon="/quickstart/aspplus/images/ctrlauth6.gif"
Caption="JScript Composition2.aspx"
runat="server" />
</JsTemplate>
</Acme:LangSwitch>
<!--BEGIN SECTION-->
<p>
<a name="exposingevts"><br> <span class="subhead">从复合控件引发自定义事件</span>
<p>
复合控件可以定义自定义事件,通过引发该事件来响应其子控件引发的事件。
<p>
下面的示例显示复合控件 <code>Composition3</code>,该控件引发自定义事件 <code>Change</code> 以响应 <b>TextBox</b> 子控件的 <b>TextChanged</b> 事件。
<p>
实现方法如下:
<ul>
<li>自定义 <code>Change</code> 事件通过标准事件模式定义。(该模式包括受保护的 <code>OnChange</code> 方法的定义,该方法将引发 <code>Change</code> 事件。)
<p><Acme:TabControl runat="server">
<Tab Name="C#">
public event EventHandler Change;
protected void OnChange(EventArgs e) {
Change(this, e);
}
</Tab>
<Tab Name="VB">
Public Event Change(Sender as Object, E as EventArgs)
Protected Sub OnChange(e As EventArgs)
Change(Me, e)
End Sub
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -