共用方式為


伺服器控制項屬性範例

更新:2007 年 11 月

本範例示範如何建立名為 Book 的控制項,這個控制項會保存簡單屬性和含有子屬性的屬性。

簡單屬性是其型別為字串,或型別可方便對應至字串的屬性。簡單屬性 (Property) 會在控制項的開頭標記上當做屬性 (Attribute) 保存,而不需要您執行任何動作。String 型別的屬性和 .NET Framework 類別庫中的基本實值型別 (例如 BooleanInt16Int32Enum),都是簡單屬性。您可以針對跨回傳 (Postback) 的狀態管理,加入程式碼以便在 ViewState 字典中存放簡單屬性。

當屬性型別也是一個類別同時本身具有屬性 (也就是子屬性) 的類別時,稱為複雜屬性。例如,WebControlFont 屬性型別是 FontInfo 類別,而 FontInfo 屬性包含像是 BoldName 的屬性。而 BoldNameWebControlFont 屬性的子屬性。ASP.NET Web 網頁架構會使用連字號連接的語法 (例如,Font-Bold="true") 在控制項的開頭標記上保存子屬性,但是在控制項的標記內 (例如,<font Bold="true">) 保存子屬性時,能夠更容易讀取子屬性。

若要讓視覺化設計工具 (Visual Designer) 將子屬性保存為控制項子系,必須將數個設計階段屬性 (Attribute) 套用至屬性 (Property) 與其型別;預設持續性 (Persistence) 是在控制項的標記上以連字號連接的屬性 (Attribute)。此外,具有子屬性的屬性也需要自訂狀態管理才能使用檢視狀態,如本主題稍後的「程式碼討論」章節所述。

範例中定義的 Book 控制項是可以在網頁中使用的控制項,以顯示目錄中的書籍詳細資訊。Book 控制項會定義下列屬性:

  • Author,具有子屬性的屬性,其型別是自訂型別 Author。Author 型別具有本身的屬性,例如 FirstName 和 LastName,這些是 Author 屬性的子屬性。

  • BookType,簡單屬性,其型別是自訂列舉型別 BookType。BookType 列舉型別具有如 Fiction 和 NonFiction 的值。

  • CurrencySymbol,內建 String 型別的簡單屬性。

  • Price,內建 Decimal 型別的簡單屬性。

  • Title,內建 String 型別的簡單屬性。

BookType、CurrencySymbol、Price 和 Title 屬性 (Property) 都是簡單屬性 (Property),因此在網頁持續性上不需要任何特殊屬性 (Attribute)。網頁架構預設會在控制項標記上將這些屬性 (Property) 保存為屬性 (Attribute),如下列範例所示:

<aspSample:Book Title="Wingtip Toys Stories" 
  CurrencySymbol="$" 
  Price="16" 
  BookType="Fiction">
</aspSample:Book>

Author 屬性 (Property) 和 Author 類別的屬性 (Property) 需要設計階段屬性 (Attribute),以啟用控制項標記中的持續性,如下列範例所示:

<aspSample:Book >
  <Author FirstName="Judy" LastName="Lew" />
</aspSample:Book>

Book 控制項會將簡單屬性存放在 ViewState 字典中。但是,Book 控制項必須對 Author 屬性實作自訂狀態管理,以跨回傳 (Postback) 管理屬性的狀態。

Book 控制項的實際執行品質實作可定義其他書籍相關的屬性,例如發行者和發行日期。此外,Author 屬性可以使用集合屬性取代。如需實作集合屬性的詳細資訊,請參閱 Web 控制項集合屬性範例

注意事項:

網頁開發人員可以停用網頁的檢視狀態,或停用網頁中個別控制項的檢視狀態。如果控制項需要跨回傳維護重要狀態以在內部運作,您可以使用在 ASP.NET 2.0 中定義的控制項狀態機制。控制項狀態會在控制項狀態和檢視狀態的比較範例中描述。

Book 控制項的程式碼清單

' Book.vb
Option Strict On
Imports System
Imports System.ComponentModel
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("Title"), _
    ToolboxData("<{0}:Book runat=""server""> </{0}:Book>") _
    > _
    Public Class Book
        Inherits WebControl
        Private authorValue As Author
        Private initialAuthorString As String

        < _
        Bindable(True), _
        Category("Appearance"), _
        DefaultValue(""), _
        Description("The name of the author."), _
        DesignerSerializationVisibility( _
            DesignerSerializationVisibility.Content), _
        PersistenceMode(PersistenceMode.InnerProperty) _
        > _
        Public Overridable ReadOnly Property Author() As Author
            Get
                If (authorValue Is Nothing) Then
                    authorValue = New Author()
                End If
                Return authorValue
            End Get
        End Property

        < _
        Bindable(True), _
        Category("Appearance"), _
        DefaultValue(BookType.NotDefined), _
        Description("Fiction or Not") _
        > _
        Public Overridable Property BookType() As BookType
            Get
                Dim t As Object = ViewState("BookType")
                If t Is Nothing Then t = BookType.NotDefined
                Return CType(t, BookType)
            End Get
            Set(ByVal value As BookType)
                ViewState("BookType") = value
            End Set
        End Property

        < _
        Bindable(True), _
        Category("Appearance"), _
        DefaultValue(""), _
        Description("The symbol for the currency."), _
        Localizable(True) _
        > _
        Public Overridable Property CurrencySymbol() As String
            Get
                Dim s As String = CStr(ViewState("CurrencySymbol"))
                If s Is Nothing Then s = String.Empty
                Return s
            End Get
            Set(ByVal value As String)
                ViewState("CurrencySymbol") = value
            End Set
        End Property

        < _
        Bindable(True), _
        Category("Appearance"), _
        DefaultValue("0.00"), _
        Description("The price of the book."), _
        Localizable(True) _
        > _
        Public Overridable Property Price() As Decimal
            Get
                Dim p As Object = ViewState("Price")
                If p Is Nothing Then p = Decimal.Zero
                Return CType(p, Decimal)
            End Get
            Set(ByVal value As Decimal)
                ViewState("Price") = value
            End Set
        End Property

        < _
        Bindable(True), _
        Category("Appearance"), _
        DefaultValue(""), _
        Description("The title of the book."), _
        Localizable(True) _
        > _
        Public Overridable Property Title() As String
            Get
                Dim s As String = CStr(ViewState("Title"))
                If s Is Nothing Then s = String.Empty
                Return s
            End Get
            Set(ByVal value As String)
                ViewState("Title") = value
            End Set
        End Property

        Protected Overrides Sub RenderContents( _
            ByVal writer As HtmlTextWriter)
            writer.RenderBeginTag(HtmlTextWriterTag.Table)

            writer.RenderBeginTag(HtmlTextWriterTag.Tr)
            writer.RenderBeginTag(HtmlTextWriterTag.Td)
            writer.WriteEncodedText(Title)
            writer.RenderEndTag()
            writer.RenderEndTag()

            writer.RenderBeginTag(HtmlTextWriterTag.Tr)
            writer.RenderBeginTag(HtmlTextWriterTag.Td)
            writer.WriteEncodedText(Author.ToString())
            writer.RenderEndTag()
            writer.RenderEndTag()

            writer.RenderBeginTag(HtmlTextWriterTag.Tr)
            writer.RenderBeginTag(HtmlTextWriterTag.Td)
            writer.WriteEncodedText(BookType.ToString())
            writer.RenderEndTag()
            writer.RenderEndTag()

            writer.RenderBeginTag(HtmlTextWriterTag.Tr)
            writer.RenderBeginTag(HtmlTextWriterTag.Td)
            writer.Write(CurrencySymbol)
            writer.Write("&nbsp")
            writer.Write(String.Format("{0:F2}", Price))
            writer.RenderEndTag()
            writer.RenderEndTag()

            writer.RenderEndTag()
        End Sub

        Protected Overrides Sub LoadViewState( _
            ByVal savedState As Object)
            MyBase.LoadViewState(savedState)
            Dim auth As Author = CType(ViewState("Author"), Author)
            If auth IsNot Nothing Then
                authorValue = auth
            End If
        End Sub

        Protected Overrides Function SaveViewState() As Object
            If authorValue IsNot Nothing Then
                Dim currentAuthorString As String = _
                    authorValue.ToString()
                If Not _
                    (currentAuthorString.Equals(initialAuthorString)) Then
                    ViewState("Author") = authorValue
                End If
            End If
            Return MyBase.SaveViewState()
        End Function

        Protected Overrides Sub TrackViewState()
            If authorValue IsNot Nothing Then
                initialAuthorString = authorValue.ToString()
            End If
            MyBase.TrackViewState()
        End Sub

    End Class
End Namespace
// Book.cs
using System;
using System.ComponentModel;
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("Title"),
    ToolboxData("<{0}:Book runat=\"server\"> </{0}:Book>")
    ]
    public class Book : WebControl
    {
        private Author authorValue;
        private String initialAuthorString;

        [
        Bindable(true),
        Category("Appearance"),
        DefaultValue(""),
        Description("The name of the author."),
        DesignerSerializationVisibility(
            DesignerSerializationVisibility.Content),
        PersistenceMode(PersistenceMode.InnerProperty),
        ]
        public virtual Author Author
        {
            get
            {
                if (authorValue == null)
                {
                    authorValue = new Author();
                }
                return authorValue;
            }

        }

        [
        Bindable(true),
        Category("Appearance"),
        DefaultValue(BookType.NotDefined),
        Description("Fiction or Not"),
        ]
        public virtual BookType BookType
        {
            get
            {
                object t = ViewState["BookType"];
                return (t == null) ? BookType.NotDefined : (BookType)t;
            }
            set
            {
                ViewState["BookType"] = value;
            }
        }

        [
        Bindable(true),
        Category("Appearance"),
        DefaultValue(""),
        Description("The symbol for the currency."),
        Localizable(true)
        ]
        public virtual string CurrencySymbol
        {
            get
            {
                string s = (string)ViewState["CurrencySymbol"];
                return (s == null) ? String.Empty : s;
            }
            set
            {
                ViewState["CurrencySymbol"] = value;
            }
        }


        [
        Bindable(true),
        Category("Appearance"),
        DefaultValue("0.00"),
        Description("The price of the book."),
        Localizable(true)
        ]
        public virtual Decimal Price
        {
            get
            {
                object price = ViewState["Price"];
                return (price  == null) ? Decimal.Zero : (Decimal)price;
            }
            set
            {
                ViewState["Price"] = value;
            }
        }

        [
        Bindable(true),
        Category("Appearance"),
        DefaultValue(""),
        Description("The title of the book."),
        Localizable(true)
        ]
        public virtual string Title
        {
            get
            {
                string s = (string)ViewState["Title"];
                return (s == null) ? String.Empty : s;
            }
            set
            {
                ViewState["Title"] = value;
            }
        }

        protected override void RenderContents(HtmlTextWriter writer)
        {
            writer.RenderBeginTag(HtmlTextWriterTag.Table);

            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.WriteEncodedText(Title);
            writer.RenderEndTag();
            writer.RenderEndTag();

            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.WriteEncodedText(Author.ToString());
            writer.RenderEndTag();
            writer.RenderEndTag();

            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.WriteEncodedText(BookType.ToString());
            writer.RenderEndTag();
            writer.RenderEndTag();

            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.Write(CurrencySymbol);
            writer.Write("&nbsp;");
            writer.Write(String.Format("{0:F2}", Price));
            writer.RenderEndTag();
            writer.RenderEndTag();

            writer.RenderEndTag();
        }

        protected override void LoadViewState(object savedState)
        {
            base.LoadViewState(savedState);

            Author auth = (Author)ViewState["Author"];
            if (auth != null)
            {
                authorValue = auth;
            }
        }

        protected override object SaveViewState()
        {
            if (authorValue != null)
            {
                String currentAuthorString = authorValue.ToString();
                if (!(currentAuthorString.Equals(initialAuthorString)))
                {
                    ViewState["Author"] = authorValue;
                }
            }

            return base.SaveViewState();
        }

        protected override void TrackViewState()
        {
            if (authorValue != null)
            {
                initialAuthorString = authorValue.ToString();
            }
            base.TrackViewState();
        }

    }
}

程式碼討論

套用至 Book 控制項 Author 屬性的 DesignerSerializationVisibilityAttributePersistenceModeAttribute,會在 Web 控制項集合屬性範例中描述。序列化和保存 Author 類別的屬性 (Property) 時,會需要這些屬性 (Attribute)。

檢視狀態 (View State) 機制會參考 ASP.NET 用於維護跨回傳 (Postback) 狀態的技術。此機制會在網頁處理結束時,將網頁狀態及其控制項樹狀結構序列化至字串表示,然後在回傳時還原序列化字串。根據預設,網頁會將字串傳送至瀏覽器做為隱藏欄位。如需詳細資訊,請參閱 ASP.NET 狀態管理概觀

若要管理簡單屬性的狀態,可將之定義為存放在控制項 ViewState 屬性中的可讀/寫屬性。Book 控制項會使用這個方法定義其簡單屬性 (BookType、CurrencySymbol、Price 和 Title)。將為您管理存放在 ViewState 屬性中的屬性狀態,而不需要採取任何動作。

若要管理具有子屬性的屬性,可以將屬性定義為唯讀,並撰寫程式碼以管理物件的狀態。若要完成這項作業,可以覆寫下列方法:

ViewState 屬性的型別 StateBag,是具有內建狀態管理的字典。StateBag 類別會實作 IStateManager 介面,可定義 TrackViewStateSaveViewStateLoadViewState 方法。StateBag 類別會實作這些方法,以便在初始設定之後開始追蹤控制項屬性的變更、於網頁要求結束時儲存修改的項目,並在回傳時將儲存的狀態載入項目。如果在對網頁要求執行 OnInit 方法之後設定項目,StateBag 會將項目標記為已修改,對這些項目進行追蹤。例如,如果網頁上的程式碼在網頁初始設定之後執行,並設定 Book 控制項的 Title 屬性,則會對 ViewState["Title"] 產生變更。因此,在 ViewState 中的 "Title"索引鍵下存放的值,會標記為已修改。如需詳細資訊,請參閱 ASP.NET 網頁存留週期概觀

Book 控制項會將 Author 屬性定義為唯讀屬性,並實作自訂狀態管理,如下所示:

  • 在 TrackViewState 方法中,Book 控制項會先將初始 Author 屬性儲存至字串,然後透過叫用基底類別的 TrackViewState 方法,開始進行狀態追蹤。

  • 在 SaveViewState 方法中,Book 控制項會判斷 Author 屬性是否已從初始值變更。如果屬性已變更,Book 會使用索引鍵 "Author",將 Author 屬性儲存在 ViewState 字典中。Book 控制項接著會叫用基底類別的 SaveViewState 方法。由於已啟動狀態追蹤,儲存在 ViewState 的 Author 物件會自動標記為已修改,並當做基底類別檢視狀態的一部分儲存。

  • 在 LoadViewState 中,Book 控制項會先叫用基底類別的 LoadViewState 方法。這個呼叫會自動還原 ViewState 字典。Book 控制項接著會判斷,ViewState 字典是否具有存放在 "Author" 下的項目。如果有的話,控制項會將檢視狀態值載入 Author 屬性。

Author 型別 (在隨後列出的程式碼中定義) 具有自訂型別轉換子 (Type Converter),因此可以在檢視狀態中存放 Author 執行個體。型別轉換子會將 Author 執行個體轉換為字串,反之亦然。定義型別轉換子可允許在視覺化設計工具中設定 Author 的子屬性。自訂型別轉換子會在型別轉換子範例中描述。您可以存放在檢視狀態中的型別是由 LosFormatter 類別所限制,ASP.NET 會使用這個類別進行檢視狀態序列化 (Serialization)。能夠最有效序列化的型別為 String、NET Framework 類別庫中的基本實值型別 (例如 BooleanInt16Int32EnumPairTripletArrayArrayListHashtable),以及包含這些基本型別 (Primitive Type) 的型別。此外,您也可以在檢視狀態中存放自訂型別,這些型別具有定義的型別轉換子,例如 PairTripletArrayArrayListHashtable。對控制項定義檢視狀態序列化時,必須將控制項資料轉換為下列其中一個型別。如果將型別存放在與檢視狀態序列化機制不相容的檢視狀態,控制項可能會進行編譯,但會在執行階段時產生錯誤。最後,可序列化型別 (也就是實作 ISerializable 介面或使用 SerializableAttribute 標記的型別) 可以存放在檢視狀態,但這些型別的序列化速度明顯會比基本型別還慢。

控制項對序列化所產生的狀態物件是控制項的檢視狀態。控制項的 ViewState 屬性只是控制項檢視狀態的一小部分,它可以是自動參與檢視狀態機制的屬性,而不需要您採取任何動作。Control 類別會實作邏輯,以便使用 SaveViewStateLoadViewState 方法,將已修改的項目儲存和載入 ViewState 字典中。其他檢視狀態部分是額外的物件,您 (和控制項基底類別) 可覆寫 SaveViewState 方法,將額外的物件儲存在檢視狀態中。覆寫 SaveViewState 和 LoadViewState 方法時,必須呼叫基底類別的對應方法。

Author 類別的程式碼清單

NotifyParentPropertyAttribute 套用至 FirstName、LastName 和 MiddleName 屬性 (Property),並將屬性 (Attribute) 的建構函式引數設為 true,會讓視覺化設計工具將這些屬性 (Property) 的變更傳送並序列化至其父屬性 (Author 執行個體)。

' Author.vb
Option Strict On
Imports System
Imports System.Collections
Imports System.ComponentModel
Imports System.Globalization
Imports System.Web.UI

Namespace Samples.AspNet.VB.Controls
    < _
    TypeConverter(GetType(AuthorConverter)) _
    > _
    Public Class Author
        Dim firstNameValue As String
        Dim lastNameValue As String
        Dim middleNameValue As String

        Public Sub New()
            Me.New(String.Empty, String.Empty, String.Empty)
        End Sub

        Public Sub New(ByVal firstname As String, _
            ByVal lastname As String)
            Me.New(firstname, String.Empty, lastname)
        End Sub

        Public Sub New(ByVal firstname As String, _
            ByVal middlename As String, ByVal lastname As String)
            firstNameValue = firstname
            middleNameValue = middlename
            lastNameValue = lastname
        End Sub

        < _
        Category("Behavior"), _
        DefaultValue(""), _
        Description("First name of author."), _
        NotifyParentProperty(True) _
        > _
        Public Overridable Property FirstName() As String
            Get
                Return firstNameValue
            End Get
            Set(ByVal value As String)
                firstNameValue = value
            End Set
        End Property


        < _
        Category("Behavior"), _
        DefaultValue(""), _
        Description("Last name of author."), _
        NotifyParentProperty(True) _
        > _
        Public Overridable Property LastName() As String
            Get
                Return lastNameValue
            End Get
            Set(ByVal value As String)
                lastNameValue = value
            End Set
        End Property

        < _
        Category("Behavior"), _
        DefaultValue(""), _
        Description("Middle name of author."), _
            NotifyParentProperty(True) _
        > _
        Public Overridable Property MiddleName() As String
            Get
                Return middleNameValue
            End Get
            Set(ByVal value As String)
                middleNameValue = value
            End Set
        End Property

        Public Overrides Function ToString() As String
            Return ToString(CultureInfo.InvariantCulture)
        End Function

        Public Overloads Function ToString( _
            ByVal culture As CultureInfo) As String
            Return TypeDescriptor.GetConverter( _
                Me.GetType()).ConvertToString(Nothing, culture, Me)
        End Function
    End Class
End Namespace
// Author.cs
using System;
using System.Collections;
using System.ComponentModel;
using System.Globalization;
using System.Web.UI;

namespace Samples.AspNet.CS.Controls
{
    [
    TypeConverter(typeof(AuthorConverter))
    ]
    public class Author
    {
        private string firstnameValue;
        private string lastnameValue;
        private string middlenameValue;

        public Author()
            :
            this(String.Empty, String.Empty, String.Empty)
        {
        }

        public Author(string firstname, string lastname)
            :
            this(firstname, String.Empty, lastname)
        {
        }

        public Author(string firstname, 
                    string middlename, string lastname)
        {
            firstnameValue = firstname;
            middlenameValue = middlename;
            lastnameValue = lastname;
        }

        [
        Category("Behavior"),
        DefaultValue(""),
        Description("First name of author."),
        NotifyParentProperty(true),
        ]
        public virtual String FirstName
        {
            get
            {
                return firstnameValue;
            }
            set
            {
                firstnameValue = value;
            }
        }

        [
        Category("Behavior"),
        DefaultValue(""),
        Description("Last name of author."),
        NotifyParentProperty(true)
        ]
        public virtual String LastName
        {
            get
            {
                return lastnameValue;
            }
            set
            {
                lastnameValue = value;
            }
        }

        [
        Category("Behavior"),
        DefaultValue(""),
        Description("Middle name of author."),
        NotifyParentProperty(true)
        ]
        public virtual String MiddleName
        {
            get
            {
                return middlenameValue;
            }
            set
            {
                middlenameValue = value;
            }
        }

        public override string ToString()
        {
            return ToString(CultureInfo.InvariantCulture);
        }

        public string ToString(CultureInfo culture)
        {
            return TypeDescriptor.GetConverter(
                GetType()).ConvertToString(null, culture, this);
        }
    }
}

BookType 列舉型別的程式碼清單

' BookType.vb
Option Strict On
Imports System

Namespace Samples.AspNet.VB.Controls
    Public Enum BookType
        NotDefined = 0
        Fiction = 1
        NonFiction = 2
    End Enum
End Namespace
// BookType.cs
using System;

namespace Samples.AspNet.CS.Controls
{
    public enum BookType
    {
        NotDefined = 0,
        Fiction = 1,
        NonFiction = 2
    }
}

Book 控制項的測試頁

下列範例顯示使用 Book 控制項的 .aspx 網頁。

<%@ Page Language="C#" Debug="true" Trace="true"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script >
  void Button_Click(object sender, EventArgs e)
  {
    Book1.Author.FirstName = "Bob";
    Book1.Author.LastName = "Kelly";
    Book1.Title = "Contoso Stories";
    Book1.Price = 39.95M;
    Button1.Visible = false;
  }  
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
  <head id="Head1" >
    <title>
      Book test page
    </title>
  </head>
  <body>
    <form id="Form1" >
      <aspSample:Book ID="Book1" Runat="server"  
        Title="Tailspin Toys Stories" CurrencySymbol="$" 
        BackColor="#FFE0C0" Font-Names="Tahoma" 
        Price="16" BookType="Fiction">
        <Author FirstName="Judy" LastName="Lew" />
      </aspSample:Book>
      <br />
      <asp:Button ID="Button1" OnClick="Button_Click" 
        Runat="server" Text="Change" />
      <asp:Button ID="Button2" Runat="server" Text="Refresh" />
      <br />
      <br />
      <asp:HyperLink ID="Hyperlink1" href="BookTest.aspx" 
        Runat="server">
        Reload Page</asp:HyperLink>
    </form>
  </body>
</html>

建置及使用範例

使用在型別轉換子範例中所列出的 AuthorConverter 類別,編譯這個範例中的類別。

如需編譯及使用自訂控制項範例的詳細資訊,請參閱建置自訂伺服器控制項範例

請參閱

概念

一般型別系統中的實值型別

參考

IsPrimitive

其他資源

開發自訂的 ASP.NET 伺服器控制項