Web 控制項集合屬性範例
更新:2007 年 11 月
這個範例示範如何建立名稱為 QuickContacts 的控制項,這個控制項會對集合屬性實作網頁中的持續性。範例控制項是允許網頁開發人員儲存通訊錄連絡人清單的控制項。QuickContacts 控制項會公開 (Expose) Contacts 集合屬性,其中包含 Contact 物件。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 控制項的程式碼清單
' 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") 屬性加入至控制項。ParseChildrenAttribute 的第一個引數 (true) 指定網頁剖析器 (Parser) 應該將控制項標記中的巢狀內容當做屬性來解析,而非當作子控制項。第二個引數 ("Contacts") 提供內部預設屬性的名稱。指定第二個引數時,控制項標記中的內容必須僅對應至預設的內部屬性 (Contact 物件)。
QuickContacts 控制項也包括下列設計階段屬性 (Attribute),您必須針對設計階段序列化 (Serialization) 和持續性 (Persistence) 將這些屬性 (Attribute) 套用至集合屬性 (Property):
DesignerSerializationVisibilityAttribute:設定 Content 參數,指定視覺化設計工具 (Visual Designer) 應該序列化屬性的內容。在範例中,屬性包含 Contact 物件。
PersistenceModeAttribute:剖析 InnerDefaultProperty 參數,指定視覺化設計工具應該持續 (Persist) 套用屬性 (Attribute) 的屬性 (Property),做為內部預設屬性 (Property)。這表示視覺化設計工具會持續控制項標記中的屬性。屬性 (Attribute) 只可套用至一個屬性 (Property),因為只有一個屬性 (Property) 可以在控制項標記中持續。屬性值不會被特殊標記所包含 (包裝)。
QuickContacts 控制項會使用 EditorAttribute,使集合編輯器與 Contacts 集合屬性產生關聯,如下列範例所示:
Editor(typeof(ContactCollectionEditor), typeof(UITypeEditor))
Editor(GetType(ContactCollectionEditor), GetType(UITypeEditor))
使集合編輯器與屬性產生關聯會讓視覺化設計工具中的屬性瀏覽器開啟集合編輯器,以加入 Contact 項目。這類似於編輯 DropDownList 或 ListBox 控制項之 Items 屬性的使用者介面 (UI)。QuickContacts 使用的自訂集合編輯器 ContactCollectionEditor,會在集合編輯器範例中描述。
為了避免混淆,QuickContacts 控制不會定義強型別 (Strongly Typed) 集合,反而會使用 ArrayList 做為集合型別。一般來說,您應該使用強型別集合做為集合屬性的型別,這樣應用程式開發人員無法將任意型別加入至集合。
Contact 類別的程式碼清單
屬性 (Property) 編輯和設計階段序列化需要 Contact 類別之程式碼中的設計階段屬性 (Attribute)。與 Contact 類別關聯的 ExpandableObjectConverter 型別轉換子 (Type Converter) (使用 TypeConverterAttribute),可讓集合編輯器提供展開/摺疊使用者介面,以編輯子屬性 (Name、Email、Phone)。這類似於在視覺化設計工具的屬性瀏覽器中,編輯 Web 控制項的 Font 屬性時所看到的 UI。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 控制項的測試網頁
下列範例顯示使用 QuickContacts 控制項的 .aspx 網頁。
<%@ 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>
建置及使用範例
以列在集合編輯器範例中的 ContactCollectionEditor 編輯器,編譯 QuickContacts 控制項和 Contacts 類別。您必須將參考加入至 System.Design 組譯碼 (Assembly),以進行編譯。
如需編譯及使用自訂控制項範例的詳細資訊,請參閱建置自訂伺服器控制項範例。