ASP.NET
集合编辑器示例
此示例演示如何创建名为
ContactCollectionEditor
的、用于实现自定义集合编辑器的控件。该示例演示如何指定页开发人员在使用自定义集合编辑器时可以添加到控件集合属性中的对象的准确类型。通过将
EditorAttribute
应用于控件的集合属性,可使集合编辑器与集合属性(或属性的类型)关联。
如果对集合属性使用强类型
IList
实现,并且集合中的所有对象都属于同一类型,则无需使用自定义集合编辑器。在此情况下,可以将内置
CollectionEditor
用作属性编辑器,因为
CollectionEditor
可以根据
IList
实现的
Items
属性的类型来推断对象类型。应尽可能使用类型化的集合。但是,如果使用集合(如
ArrayList
)作为控件的集合属性的类型,则需使用自定义集合编辑器来指定集合项的对象类型。
本示例中描述的
ContactCollectionEditor
由
Web 控件集合属性示例
中所述的
QuickContacts
控件的
Contacts
属性使用。它使得类型为
Contact
的对象可以通过集合编辑器用户界面
(UI)
添加至
Contacts
属性中。
ContactCollectionEditor
类派生自
CollectionEditor
并重写
CreateCollectionItemType
方法,以返回
Contact
类型。
如果控件的集合属性包含不同类型的对象,则可按照与示例中相似的方法实现集合编辑器,但要重写
CreateNewItemTypes
方法,而不是
CreateCollectionItemType
方法,并返回正确的项类型。
ContactCollectionEditor
的代码清单
Visual Basic复制到剪贴板
' ContactCollectionEditor.vb
Imports
System
Imports
System.ComponentModel
Imports
System.ComponentModel.Design
Imports
System.Reflection
Namespace
Samples.AspNet.VB.Controls
Public Class ContactCollectionEditor
Inherits CollectionEditor
Public Sub New(ByVal newType As Type)
MyBase.new(newType)
End Sub
Protected Overrides Function CanSelectMultipleInstances() _
As Boolean
Return False
End Function
Protected Overrides Function CreateCollectionItemType() As Type
Return GetType(Contact)
End Function
End Class
End
Namespace
C#复制到剪贴板
// ContactCollectionEditor.cs
using
System;
using
System.ComponentModel;
using
System.ComponentModel.Design;
using
System.Reflection;
namespace
Samples.AspNet.CS.Controls
{
public class ContactCollectionEditor : CollectionEditor
{
public ContactCollectionEditor(Type type)
: base(type)
{
}
protected override bool CanSelectMultipleInstances()
{
return false;
}
protected override Type CreateCollectionItemType()
{
return typeof(Contact);
}
}
}
生成和使用示例
使用
Web 控件集合属性示例
中列出的
QuickContacts
控件和
Contacts
类来编译
ContactCollectionEditor
编辑器。必须添加对
System.Design
程序集的引用才能进行编译。
请参见
概念
其他资源
ASP.NET
Web
控件集合属性示例
此示例演示如何创建一个名为
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
控件的代码清单
Visual Basic复制到剪贴板
' 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
C#复制到剪贴板
// 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)
值不会用特殊标记包装。
C#复制到剪贴板
Editor(typeof(ContactCollectionEditor), typeof(UITypeEditor))
Visual Basic复制到剪贴板
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
类的一个实例)。
Visual Basic复制到剪贴板
' 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
C#复制到剪贴板
// 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
页。
Visual Basic复制到剪贴板
<%@ Page Language="VB"%>
<html>
<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>
C#复制到剪贴板
<%@ Page Language="C#"%>
<html>
<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
程序集的引用才能进行编译。
请参见
概念
其他资源