设置自定义控件集合编辑器属性
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 程序集的引用才能进行编译。
请参见
概念
其他资源