Web 控件集合属性示例

更新:2007 年 11 月

此示例演示如何创建一个名为 QuickContacts 的控件,该控件将在页面中实现集合属性的持久性。该示例控件是一个允许页开发人员存储通讯簿联系人列表的控件。QuickContacts 控件会公开一个包含 Contact 对象的 Contacts 集合属性。Contact 类具有 Name、Email 和 Phone 属性。

Contacts 集合属性的 Contact 项持久保存在该控件的标记中,如下面的示例所示:

<aspSample:QuickContacts ID="QuickContacts1" Runat="server">
  <aspSample:Contact Name="someone" Email="someone@example.com"     Phone="(555) 555-5555"/><aspSample:Contact Name="jae" Email="jae@fourthcoffee.com"     Phone="(555) 555-5555"/>
</aspSample:QuickContacts>

为清楚起见,QuickContacts 控件不会实现集合属性的状态管理。假设集合项以声明方式添加到页中,或者如果已在代码中创建,则必须在回发时重新创建。在高质量的控件中,将实现状态管理。有关详细信息,请参见服务器控件自定义状态管理

QuickContacts 控件的代码清单

' QuickContacts.vb
Option Strict On
Imports System
Imports System.ComponentModel
Imports System.Collections
Imports System.Drawing.Design
Imports System.Security.Permissions
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls

Namespace Samples.AspNet.VB.Controls
    < _
    AspNetHostingPermission(SecurityAction.Demand, _
        Level:=AspNetHostingPermissionLevel.Minimal), _
    AspNetHostingPermission(SecurityAction.InheritanceDemand, _
        Level:=AspNetHostingPermissionLevel.Minimal), _
    DefaultProperty("Contacts"), _
    ParseChildren(True, "Contacts"), _
    ToolboxData( _
        "<{0}:QuickContacts runat=""server""> </{0}:QuickContacts>") _
    > _
    Public Class QuickContacts
        Inherits WebControl

        Private contactsList As ArrayList

        < _
        Category("Behavior"), _
        Description("The contacts collection"), _
        DesignerSerializationVisibility( _
            DesignerSerializationVisibility.Content), _
        Editor(GetType(ContactCollectionEditor), _
            GetType(UITypeEditor)), _
        PersistenceMode(PersistenceMode.InnerDefaultProperty) _
        > _
        Public ReadOnly Property Contacts() As ArrayList
            Get
                If contactsList Is Nothing Then
                    contactsList = New ArrayList
                End If
                Return contactsList
            End Get
        End Property

        ' The contacts are rendered in an HTML table.
        Protected Overrides Sub RenderContents( _
        ByVal writer As HtmlTextWriter)
            Dim t As Table = CreateContactsTable()
            If t IsNot Nothing Then
                t.RenderControl(writer)
            End If
        End Sub

        Private Function CreateContactsTable() As Table
            Dim t As Table = Nothing
            If (contactsList IsNot Nothing) AndAlso _
                (contactsList.Count > 0) Then
                t = New Table
                For Each item As Contact In contactsList
                    Dim aContact As Contact = TryCast(item, Contact)
                    If aContact IsNot Nothing Then
                        Dim r As New TableRow
                        Dim c1 As New TableCell
                        c1.Text = aContact.Name
                        r.Controls.Add(c1)

                        Dim c2 As New TableCell
                        c2.Text = aContact.Email
                        r.Controls.Add(c2)

                        Dim c3 As New TableCell
                        c2.Text = aContact.Phone
                        r.Controls.Add(c3)

                        t.Controls.Add(r)
                    End If
                Next
            End If
            Return t
        End Function
    End Class
End Namespace
// QuickContacts.cs
using System;
using System.ComponentModel;
using System.Collections;
using System.Drawing.Design;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Samples.AspNet.CS.Controls
{
    [
    AspNetHostingPermission(SecurityAction.Demand,
        Level = AspNetHostingPermissionLevel.Minimal),
    AspNetHostingPermission(SecurityAction.InheritanceDemand, 
        Level=AspNetHostingPermissionLevel.Minimal),
    DefaultProperty("Contacts"),
    ParseChildren(true, "Contacts"),
    ToolboxData(
        "<{0}:QuickContacts runat=\"server\"> </{0}:QuickContacts>")
    ]
    public class QuickContacts : WebControl
    {
        private ArrayList contactsList;

        [
        Category("Behavior"),
        Description("The contacts collection"),
        DesignerSerializationVisibility(
            DesignerSerializationVisibility.Content),
        Editor(typeof(ContactCollectionEditor), typeof(UITypeEditor)),
        PersistenceMode(PersistenceMode.InnerDefaultProperty)
        ]
        public ArrayList Contacts
        {
            get
            {
                if (contactsList == null)
                {
                    contactsList = new ArrayList();
                }
                return contactsList;
            }
        }


        // The contacts are rendered in an HTML table.
        protected override void RenderContents(
            HtmlTextWriter writer)
        {
            Table t = CreateContactsTable();
            if (t != null)
            {
                t.RenderControl(writer);
            }
        }

        private Table CreateContactsTable()
        {
            Table t = null;

            if (contactsList != null && contactsList.Count > 0)
            {
                t = new Table();

                foreach (Contact item in contactsList)
                {
                    Contact aContact = item as Contact;

                    if (aContact != null)
                    {
                        TableRow r = new TableRow();

                        TableCell c1 = new TableCell();
                        c1.Text = aContact.Name;
                        r.Controls.Add(c1);

                        TableCell c2 = new TableCell();
                        c2.Text = aContact.Email;
                        r.Controls.Add(c2);


                        TableCell c3 = new TableCell();
                        c3.Text = aContact.Phone;
                        r.Controls.Add(c3);

                        t.Controls.Add(r);
                    }
                }
            }
            return t;
        }
    }
}

代码讨论

为了能够分析控件标记中的集合项,QuickContacts 控件在其中添加了 ParseChildren(true, "Contacts") 属性 (Attribute)。ParseChildrenAttribute 的第一个参数 (true) 指定页分析器应将控件标记内的嵌套内容解释为属性 (Property),而不是子控件。第二个参数 ("Contacts") 提供了内部默认属性 (Property) 的名称。指定第二个参数时,控件标记中的内容必须与默认的内部属性(property,Contact 对象)对应,而不与其他任何内容对应。

QuickContacts 控件还包括以下设计时属性 (Attribute),为实现设计时系列化和持久性,必须将这些属性 (Attribute) 应用于集合属性 (Property):

  • DesignerSerializationVisibilityAttribute   通过设置 Content 参数,可以指定可视化设计器应对属性的内容进行序列化。在该示例中,此属性包含 Contact 对象。

  • PersistenceModeAttribute   通过传递 InnerDefaultProperty 参数,可以指定可视化设计器应将属性 (Property) 保存为作为内部默认属性 (Property) 应用的属性 (Attribute)。这表示可视化设计器会将属性 (Property) 保存在控件的标记中。属性 (Attribute) 只能应用于一个属性 (Property),因为其对应的控件标记中只能保存一个属性 (Property)。属性 (Property) 值不会用特殊标记包装。

QuickContacts 控件使用 EditorAttribute 将集合编辑器与 Contacts 集合属性关联,如下面的示例所示:

Editor(typeof(ContactCollectionEditor), typeof(UITypeEditor))
Editor(GetType(ContactCollectionEditor), GetType(UITypeEditor))

通过将集合编辑器与属性关联,可以使可视化设计器中的属性浏览器打开集合编辑器以添加 Contact 项。这与用于编辑 DropDownList 控件或 ListBox 控件的 Items 属性的用户界面 (UI) 类似。QuickContacts 所使用的自定义集合编辑器 ContactCollectionEditor 在集合编辑器示例中进行了描述。

为了清楚起见,QuickContacts 控件不会定义强类型集合,而是使用 ArrayList 作为其集合类型。一般情况下,应该使用强类型集合作为集合属性的类型,这样应用程序开发人员就无法在集合中任意添加类型了。

Contact 类的代码清单

编辑属性 (Property) 和进行设计时序列化时,需要使用 Contact 类代码中的设计时属性 (Attribute)。与 Contact 类关联的 ExpandableObjectConverter 类型转换器(使用 TypeConverterAttribute)使集合编辑器可以提供一个用于编辑子属性(Name、Email、Phone)的展开/折叠的用户界面。该界面类似于在可视化设计器的属性浏览器中编辑 Web 控件的 Font 属性时看到的用户界面。应用于 Name、Email 和 Phone 属性的 NotifyParentPropertyAttribute(其中构造函数参数等于 true)会导致编辑器将这些属性中的更改序列化到其父属性(即 Contact 类的一个实例)。

' Contact.vb
' The type of the items in the Contacts collection property 
' in QuickContacts.
Option Strict On
Imports System
Imports System.Collections
Imports System.ComponentModel
Imports System.Web.UI

Namespace Samples.AspNet.VB.Controls
    < _
    TypeConverter(GetType(ExpandableObjectConverter)) _
    > _
    Public Class Contact
        Private _name As String
        Private _email As String
        Private _phone As String

        Public Sub New()
            Me.New(String.Empty, String.Empty, String.Empty)
        End Sub

        Public Sub New(ByVal name As String, _
        ByVal email As String, ByVal phone As String)
            _name = name
            _email = email
            _phone = phone
        End Sub

        < _
        Category("Behavior"), _
        DefaultValue(""), _
        Description("Name of contact"), _
        NotifyParentProperty(True) _
        > _
        Public Property Name() As String
            Get
                Return _name
            End Get
            Set(ByVal value As String)
                _name = value
            End Set
        End Property

        < _
        Category("Behavior"), _
        DefaultValue(""), _
        Description("Email address of contact"), _
        NotifyParentProperty(True) _
        > _
        Public Property Email() As String
            Get
                Return _email
            End Get
            Set(ByVal value As String)
                _email = value
            End Set
        End Property


        < _
        Category("Behavior"), _
        DefaultValue(""), _
        Description("Phone number of contact"), _
        NotifyParentProperty(True) _
        > _
        Public Property Phone() As String
            Get
                Return _phone
            End Get
            Set(ByVal value As String)
                _phone = value
            End Set
        End Property
    End Class
End Namespace
// Contact.cs
// The type of the items in the Contacts collection property 
//in QuickContacts.

using System;
using System.Collections;
using System.ComponentModel;
using System.Web.UI;

namespace Samples.AspNet.CS.Controls
{
    [
    TypeConverter(typeof(ExpandableObjectConverter))
    ]
    public class Contact
    {
        private string nameValue;
        private string emailValue;
        private string phoneValue;


        public Contact()
            : this(String.Empty, String.Empty, String.Empty)
        {
        }

        public Contact(string name, string email, string phone)
        {
            nameValue = name;
            emailValue = email;
            phoneValue = phone;
        }

        [
        Category("Behavior"),
        DefaultValue(""),
        Description("Name of contact"),
        NotifyParentProperty(true),
        ]
        public String Name
        {
            get
            {
                return nameValue;
            }
            set
            {
                nameValue = value;
            }
        }

        [
        Category("Behavior"),
        DefaultValue(""),
        Description("Email address of contact"),
        NotifyParentProperty(true)
        ]
        public String Email
        {
            get
            {
                return emailValue;
            }
            set
            {
                emailValue = value;
            }
        }

        [
        Category("Behavior"),
        DefaultValue(""),
        Description("Phone number of contact"),
        NotifyParentProperty(true)
        ]
        public String Phone
        {
            get
            {
                return phoneValue;
            }
            set
            {
                phoneValue = value;
            }
        }
    }
}

QuickContacts 控件的测试页

下面的示例演示一个使用 QuickContacts 控件的 .aspx 页。

<%@ Page Language="VB"%>
<!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 id="Head1" runat="server">
    <title>
      QuickContacts test page
    </title>
  </head>
  <body>
    <form id="Form1" runat="server">
      <aspSample:QuickContacts ID="QuickContacts1" Runat="server" 
        BorderStyle="Solid" BorderWidth="1px">
        <aspSample:Contact Name="someone" Email="someone@example.com" 
          Phone="(555) 555-0100"/>
        <aspSample:Contact Name="jae" Email="jae@fourthcoffee.com" 
          Phone="(555) 555-0101"/>
        <aspSample:Contact Name="lene" Email="lene@contoso.com" 
          Phone="(555) 555-0102"/>        
      </aspSample:QuickContacts>
    </form>
  </body>
</html>
<%@ Page Language="C#"%>
<!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 id="Head1" runat="server">
    <title>
      QuickContacts test page
    </title>
  </head>
  <body>
    <form id="Form1" runat="server">
      <aspSample:QuickContacts ID="QuickContacts1" Runat="server" 
        BorderStyle="Solid" BorderWidth="1px">
        <aspSample:Contact Name="someone" Email="someone@example.com" 
          Phone="(555) 555-0100"/>
        <aspSample:Contact Name="jae" Email="jae@fourthcoffee.com" 
          Phone="(555) 555-0101"/>
        <aspSample:Contact Name="lene" Email="lene@contoso.com" 
          Phone="(555) 555-0102"/>        
      </aspSample:QuickContacts>
    </form>
  </body>
</html>

生成和使用示例

使用集合编辑器示例中列出的 ContactCollectionEditor 编辑器对 QuickContacts 控件和 Contacts 类进行编译。必须添加对 System.Design 程序集的引用才能进行编译。

有关编译和使用自定义控件示例的更多信息,请参见生成自定义服务器控件示例

请参见

概念

集合编辑器示例

生成自定义服务器控件示例

其他资源

开发自定义 ASP.NET 服务器控件