答案: 页面上的控件
在添加了对包含控件的程序集的引用之后,您可以将 MailLink 控件拖动到设计器表面并像使用任何其他 ASP.net 服务器控件那样使用它。
图 6. MailLink 自定义控件
图 6 展示了 MailLink 控件的设计器视图。请注意,Properties 窗口公开了预期的 Email 和 Text 元素,它们可以用于配置控件。通过将自定义控件编译到可重复使用的程序集中,MailLink 控件可以被很多 Web 应用程序重复使用。
创建复合服务器控件
诸如 Login 和 GridView 这些可靠的控件是由很多基本控件组成的。在 ASP.NET 1.x 中,您必须通过艰苦的工作将嵌套标记和元素添加到自定义控件中来开发复合控件。在 ASP.NET 2.0 中,您可以通过扩展 System.Web.UI.WebControls.CompositeControl 类来构建复杂的复合控件。CompositeControl 类提供了将多个控件的输出合并到单个统一的控件中所必需的框架。
管理复合控件比管理基本自定义控件稍微困难一些,因为复合控件需要一些自定义布局的信息。复合控件将它们的呈现和事件处理任务委托给构成控件。子组件的所有关联的适配器类也会被自动应用。这样,如果您具有适当的适配器,复合控件将会在任何目标浏览器类型或设备上正确地呈现。
创建复合控件
创建复合控件的初始过程与创建自定义服务器控件的初始过程相似。但是,该过程还涉及了更多的步骤。在以下示例中,我们将创建一个由 Label 和 TextBox 组成的简单的复合 AgeCollector 控件,它旨在收集生日的信息。
复合控件类应该通过从 CompositeControl 继承开始。
public class AgeCollector : CompositeControl{}
定义属性
对于我们的简单控件,我们必须为标签 (Prompt) 和文本框 (DateOfBirth) 创建属性。
[Bindable(true), Category("Appearance"),
DefaultValue("Please enter your date of birth:"),
Description("Text to prompt user with.")
Localizable(true)]
public virtual String Prompt {
get
{
string s = (string)ViewState["Prompt"];
return (s == null) ? String.Empty : s;
}
set {
ViewState["Prompt"] = value;
}
}
再一次,我们使用特性为属性提供说明和默认值。我们选择了使提示可以进行本地化,以便该控件无论何时都可以用于要求进行国际化的应用程序中。实际的提示可以绑定到包含语言特定文本的资源文件。
还必须定义 DateOfBirth 属性。但是,我们不是使用 String,而是使用 DateTime 数据类型来正确地存储日期。
[Bindable(true), Category("Appearance"),
DefaultValue(""),
Description("Date of Birth Input area")]
public virtual DateTime DateOfBirth {
get
{
bject o = ViewState["DateOfBirth"];
return (o == null) ? DateTime.Now : (DateTime)o;
}
set {
ViewState["DateOfBirth"] = value;
}
}
CreateChildControls 方法
我们的复合控件由一个标签和一个文本框组成。我们无法使用简单控件的技术来显示这两个标记,除非使用强制方式和 Render() 方法。因为我们希望利用自适应呈现并显示我们的两个控件,所以我们需要覆盖内置到 CompositeControl 类中的 CreateChildControls() 方法。这种方法使我们可以定义控件,并将我们的复合控件的属性传递到要显示的单个控件中。
protected override void CreateChildControls() {
//Create and load the label
Label lab1 = new Label();
lab1.Text = Prompt;
lab1.ForeColor = this.ForeColor;
this.Controls.Add(lab1);
//Add a line break between the label and text box
Literal lit = new Literal();
lit.Text = "";
this.Controls.Add(lit);
//Add the Textbox
TextBox tb = new TextBox();
tb.ID = "tb1";
tb.Text = DateOfBirth.ToString();
this.Controls.Add(tb);
//call the parent method
base.CreateChildControls();
}
请注意,我们必须初始化每个控件、分配所有属性,然后将控件添加到内置到 CompositeControl 类中的 Controls 集合。我们还使用了 Literal 对象将换行符置于标签和控件之间。Literal 对象是非常简单的控件,您可以使用它在功能元素之间插入原始 HTML。
请注意,我们还对基本方法进行了调用,以便确保我们的复合控件具有内置到 CompositeControl 基类中的任何其他功能。尤其是,基本方易做图强制 ASP.NET 将 Controls 集合的所有元素添加到控件树中。如果我们忽略这个调用,或者将其置于我们方法的顶部,那么复合控件将不会正确地生成。
完整的 AgeCollector
当我们的 AgeCollector 控件生成时,ASP.NET 将在每个子控件上实际调用适当的方法,并将结果合并到复合控件的输出中。换句话说,如果我们已正确地设计了简单控件,那么该复合控件就只是一个容器。自适应呈现模型将会自动应用到每个子控件中。但是,实际的 CompositeControl 将不会被修改,因为它不包含需要更改的任何控件。
以下是另一个实例,其中使用的适当方法 (CreateChildControls()) 利用了自适应呈现模型,而不是简单地在 WebControl 上重载 Render() 方法。由于自适应呈现模型和 CompositeControl 的特性,ASP.NET 2.0 节省了我们的开发时间、减少了代码行数并减少了很多的测试烦恼。只要我们知道元素控件可通过特定适配器正确地生成,CompositeControl 将会通过该适配器正确地生成。
如果我们将控件拖动到 ASP.NET 页面上并查看属性,我们将会看到具有 Prompt 和 DateOfBirth 属性的单个控件。
图 7. AgeCollector 使用
请注意,如果我们将复合控件的 ForeColor 更改为红色,我们实际上更改了 Label 的 ForeColor。但是,我们尚未链接某些其他属性。例如,我们无法更改 DateOfBirth 字段的 ForeColor。换句话说,当您构建一个复合控件时,您始终需要考虑应该公开哪些子控件属性。
上一个:利用ASP.NET 2.0创建自定义Web控件(5)
下一个:利用ASP.NET 2.0创建自定义Web控件(3)