Export (0) Print
Expand All

Web Control Collection Property Example 

This example shows how to create a control named QuickContacts that implements persistence in a page for a collection property. The example control is a control that allows a page developer to store a list of address book contacts. The QuickContacts control exposes a Contacts collection property that contains Contact objects. The Contact class has Name, Email, and Phone properties.

The Contact items of the Contacts collection property are persisted within the control's tags as shown in the following example:

<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>

For clarity, the QuickContacts control does not implement state management for the collection property. The collection items are assumed to be added declaratively in the page or, if created in code, they must be recreated on postback. In a production-quality control, you would implement state management. For details, see Server Control Custom State Management.

Code Listing for the QuickContacts Control

// 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;
        }
    }
}

Code Discussion

To enable parsing of the collection items within a control's tags, the QuickContacts control adds the ParseChildren(true, "Contacts") attribute to the control. The first argument (true) of ParseChildrenAttribute specifies that the page parser should interpret nested content within the control's tags as properties and not as child controls. The second argument ("Contacts") provides the name of the inner default property. When you specify the second argument, content within the control's tags must correspond to the default inner property (Contact objects) and to nothing else.

The QuickContacts control also includes the following design-time attributes that you must apply to a collection property for design-time serialization and persistence:

  • DesignerSerializationVisibilityAttribute   Setting the Content parameter specifies that a visual designer should serialize the contents of the property. In the example, the property contains Contact objects.

  • PersistenceModeAttribute   Passing the InnerDefaultProperty parameter specifies that a visual designer should persist the property to which the attribute is applied as an inner default property. This means that a visual designer persists the property within the control's tags. The attribute can be applied to only one property, because only one property can be persisted within the control's tags. The property value is not wrapped in a special tag.

The QuickContacts control associates a collection editor with the Contacts collection property using the EditorAttribute, as in the following example:

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

Associating a collection editor with the property enables the property browser in a visual designer to open a collection editor for adding Contact items. This is similar to the user interface (UI) for editing the Items property of the DropDownList or ListBox controls. The custom collection editor used by QuickContacts, ContactCollectionEditor, is described in Collection Editor Example.

For clarity, the QuickContacts control does not define a strongly typed collection and instead uses an ArrayList for its collection type. In general, you should use a strongly typed collection as the type of the collection property so that an application developer cannot add arbitrary types to the collection.

Code Listing for the Contact Class

The design-time attributes in the code of the Contact class are needed for property editing and design-time serialization. The ExpandableObjectConverter type converter associated with the Contact class (using the TypeConverterAttribute) enables the collection editor to provide an expand/collapse user interface for editing subproperties (Name, Email, Phone). This is similar to the UI you see when editing the Font property of a Web control in the property browser of a visual designer. The NotifyParentPropertyAttribute (with the constructor argument equal to true) applied to the Name, Email, and Phone properties causes the editor to serialize changes in these properties into their parent property, an instance of the Contact class.

// 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;
            }
        }
    }
}

Test Page for the QuickContacts Control

The following example shows an .aspx page that uses the QuickContacts control.

<%@ 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>

Building and Using the Example

Compile the QuickContacts control and the Contacts class with the ContactCollectionEditor editor listed in Collection Editor Example. You must add a reference to the System.Design assembly for compilation.

For more information about compiling and using the custom control examples, see Building the Custom Server Control Examples.

See Also

Community Additions

ADD
Show:
© 2014 Microsoft