Ejemplo de propiedad Collection de controles Web
Actualización: noviembre 2007
En este ejemplo se muestra cómo crear un control denominado QuickContacts que implementa la persistencia en una página para una propiedad de colección. El ejemplo incluye un control que permite a un desarrollador de páginas almacenar una lista de contactos de libreta de direcciones. El control QuickContacts expone una propiedad de colección Contacts que contiene objetos Contact. La clase Contact tiene las propiedades Name, Email y Phone.
Los elementos Contact de la propiedad de colección Contacts se conservan dentro de las etiquetas del control, como se muestra en el ejemplo siguiente:
<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>
Por motivos de claridad, el control QuickContacts no implementa administración de estado para la propiedad de colección. Se supone que los elementos de la colección se agregan mediante declaración a la página, o bien, si se crean en código, es preciso volver a crearlos cuando se produce la devolución de datos. En un control con calidad de producción, se debería implementar la administración de estado. Para obtener información detallada, vea Administración de estados personalizados de controles de servidor.
Lista de código del control 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;
}
}
}
Descripción del código
Para habilitar el análisis de los elementos de colección en las etiquetas de un control, el control QuickContacts agrega el atributo ParseChildren(true, "Contacts") al control. El primer argumento (true) de ParseChildrenAttribute especifica que el analizador de páginas debería interpretar el contenido anidado de las etiquetas del control como propiedades, no como controles secundarios. El segundo argumento ("Contacts") proporciona el nombre de la propiedad interna predeterminada. Al especificar el segundo argumento, el contenido de las etiquetas del control debe corresponder sólo a la propiedad interna predeterminada (objetos Contact).
El control QuickContacts incluye asimismo los siguientes atributos en tiempo de diseño que deben aplicarse a una propiedad de colección para la serialización y la persistencia en tiempo de diseño:
DesignerSerializationVisibilityAttribute Si se establece el parámetro Content, se especifica que un diseñador visual debería serializar el contenido de la propiedad. En el ejemplo, la propiedad contiene objetos Contact.
PersistenceModeAttribute Si se pasa el parámetro InnerDefaultProperty, se especifica que un diseñador visual debería conservar la propiedad a la que se aplica el atributo como una propiedad interna predeterminada. Esto significa que un diseñador visual conserva la propiedad dentro de las etiquetas del control. El atributo sólo se puede aplicar a una propiedad, dado que sólo se puede conservar una propiedad en las etiquetas del control. El valor de la propiedad no se ajusta en una etiqueta especial.
El control QuickContacts asocia un editor de colecciones con la propiedad de colección Contacts utilizando EditorAttribute, como en el ejemplo siguiente:
Editor(typeof(ContactCollectionEditor), typeof(UITypeEditor))
Editor(GetType(ContactCollectionEditor), GetType(UITypeEditor))
Si se asocia un editor de colecciones a la propiedad, se habilita el examinador de propiedades en un diseñador visual para abrir un editor de colecciones y agregar elementos Contact. Esto es similar a la interfaz de usuario que se utiliza para editar la propiedad Items de los controles DropDownList o ListBox. El editor de colecciones personalizado utilizado por QuickContacts, ContactCollectionEditor, se describe en Ejemplo de editor de colección.
Por motivos de claridad, el control QuickContacts no define una colección con establecimiento inflexible de tipos; en su lugar, utiliza un objeto ArrayList para su tipo de colección. En general, se debe utilizar una colección con establecimiento inflexible de tipos como tipo de propiedad de colección a fin de que un desarrollador de aplicaciones no pueda agregar tipos arbitrarios a la colección.
Lista de código de la clase Contact
Los atributos en tiempo de diseño del código de la clase Contact son necesarios para la edición de las propiedades y la serialización en tiempo de diseño. El convertidor de tipos ExpandableObjectConverter asociado a la clase Contact (que utiliza el objeto TypeConverterAttribute) permite que el editor de colecciones proporcione la función expandir y contraer en la interfaz de usuario para editar subpropiedades (Name, Email, Phone). Esto es similar a la interfaz de usuario que aparece al editar la propiedad Font de un control Web en el examinador de propiedades de un diseñador visual. El objeto NotifyParentPropertyAttribute (con el argumento de constructor igual a true) aplicado a las propiedades Name, Email y Phone hace que el editor serialice los cambios realizados en estas propiedades en sus propiedades primarias, que son instancias de la clase 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;
}
}
}
}
Página de prueba del control QuickContacts
En el ejemplo siguiente se muestra una página .aspx que utiliza el control 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" >
<title>
QuickContacts test page
</title>
</head>
<body>
<form id="Form1" >
<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" >
<title>
QuickContacts test page
</title>
</head>
<body>
<form id="Form1" >
<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>
Generar y utilizar el ejemplo
Compile el control QuickContacts y la clase Contacts con el editor ContactCollectionEditor incluido en Ejemplo de editor de colección. Debe agregar una referencia al ensamblado System.Design para la compilación.
Para obtener más información sobre la compilación y el uso de los ejemplos de controles personalizados, vea Generar ejemplos de controles de servidor personalizados.
Vea también
Conceptos
Ejemplo de editor de colección
Generar ejemplos de controles de servidor personalizados