Пример свойства-коллекции веб-элементов
Обновлен: Ноябрь 2007
В этом примере демонстрируется создание элемента управления с именем QuickContacts, который реализует сохранение на странице свойства-коллекции. В примере используется элемент управления, позволяющий разработчику страницы хранить список адресов книги контактов. Элемент управления QuickContacts предоставляет свойство-коллекцию Contacts, содержащее объекты Contact. Класс Contact имеет свойства Name, Email и Phone.
Элементы Contact из Contacts свойства-коллекции сохраняются внутри тегов элемента управления, как показано в следующем примере:
<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") к элементу управления. Первый аргумент (true) из ParseChildrenAttribute указывает, что анализатор страницы должен интерпретировать вложенное содержимое внутри тегов элемента управления как свойства, а не как дочерние элементы. Второй аргумент ("Contacts") предоставляет имя внутреннего свойства по умолчанию. При указании второго аргумента содержимое в тегах элемента управления должно соответствовать внутреннему свойству по умолчанию (объекты Contact) и ничему другому.
Элемент управления QuickContacts также включает следующие атрибуты разработки, которые необходимо применить к свойству-коллекции для сериализации при разработке и сохранения:
DesignerSerializationVisibilityAttribute. Установка параметра Content указывает, что визуальный конструктор должен сериализовать содержимое свойства. В примере свойство содержит объекты Contact.
PersistenceModeAttribute. Передача параметра InnerDefaultProperty указывает, что визуальный конструктор должен сохранять свойство, к которому атрибут применен как внутреннее свойство по умолчанию. Это означает, что визуальный конструктор сохраняет свойство в тегах элемента управления. Атрибут может быть применен только к одному свойству, поскольку только одно свойство может быть сохранено внутри тегов элемента управления. Значение свойства не упаковывается в специальный тег.
Элемент управления QuickContacts связывает редактор коллекции со свойством-коллекцией Contacts с помощью EditorAttribute, как в следующем примере:
Editor(typeof(ContactCollectionEditor), typeof(UITypeEditor))
Editor(GetType(ContactCollectionEditor), GetType(UITypeEditor))
Сопоставление редактора коллекции со свойством позволяет обозревателю свойств в визуальном конструкторе открыть редактор коллекции для добавления элементов Contact. Он похож на пользовательский интерфейс (UI) для редактирования свойств Items из элементов управления DropDownList или ListBox. Пользовательский редактор коллекции, используемый элементами QuickContacts, ContactCollectionEditor, описан в Пример редактора коллекций.
Для ясности элемент управления QuickContacts не определяет строго типизированную коллекцию и вместо этого использует ArrayList для типа его коллекции. В общем случае следует использовать строго типизированную коллекцию в качестве типа свойства-коллекции так, чтобы разработчик приложения не смог добавить произвольный тип в коллекцию.
Листинг кода класса Contact
Атрибуты времени разработки в коде класса Contact требуются для редактирования свойства и сериализации времени разработки. Преобразователь типов ExpandableObjectConverter, связанный с классом Contact (при помощи TypeConverterAttribute), позволяет редактору коллекции предоставить интерфейс пользователя с возможностью развертки/свертки для редактирования субсвойства (Name, Email, Phone). Это похоже на пользовательский интерфейс при редактировании свойства Font веб-элемента управления в обозревателе визуального конструктора. NotifyParentPropertyAttribute (с аргументом конструктора равным true), применяемый к свойствам Name, Email и Phone, вызывает редактор для сериализации изменений в этих свойствах в их родительское свойство, экземпляр класса 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
В следующем примере показана страница .aspx, использующая элемент управления QuickContacts:
<%@ 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>
Построение и использование примеров
Скомпилируйте элемент управления QuickContacts и класс Contacts с редактором ContactCollectionEditor, описанным в Пример редактора коллекций. Для компиляции необходимо добавить ссылку на сборку System.Design.
Дополнительные сведения о компиляции и использовании примеров пользовательских элементов управления содержатся в разделе Примеры связывания пользовательского серверного элемента управления.
См. также
Основные понятия
Примеры связывания пользовательского серверного элемента управления
Другие ресурсы
Разработка пользовательских серверных элементов управления ASP.NET