Compartir a través de


Ejemplo de propiedades de controles de servidor

Actualización: noviembre 2007

En este ejemplo se muestra cómo crear un control denominado Book que conserva propiedades simples y propiedades que tienen subpropiedades.

Una propiedad simple es una propiedad cuyo tipo es una cadena o un tipo que se asigna fácilmente a una cadena. Una propiedad simple se conserva como atributo en la etiqueta de apertura del control sin que sea necesario realizar ninguna operación adicional. Las propiedades del tipo String y los tipos de valores primitivos de la biblioteca de clases de .NET Framework como Boolean, Int16, Int32 y Enum son propiedades simples. Es posible agregar código para almacenar una propiedad simple en el diccionario de ViewState para la administración de estado en las distintas devoluciones de datos.

Una propiedad se denomina compleja cuando el tipo de propiedad es una clase que tiene propiedades en sí misma, las cuales se denominan subpropiedades. Por ejemplo, el tipo de la propiedad Font de WebControl es la clase FontInfo, que tiene propiedades como Bold y Name. Bold y Name son subpropiedades de la propiedad Font de WebControl. El marco de trabajo de las páginas ASP.NET puede conservar subpropiedades en la etiqueta de apertura de un control utilizando sintaxis con guiones (por ejemplo, Font-Bold="true"), pero las subpropiedades son más legibles en la página cuando se conservan dentro de las etiquetas del control (por ejemplo, <font Bold="true">).

Para permitir que un diseñador visual conserve las subpropiedades como elementos secundarios del control, debe aplicar varios atributos en tiempo de diseño a la propiedad y su tipo; la conservación predeterminada consiste en atributos con guiones en la etiqueta del control. Por otra parte, una propiedad que tiene subpropiedades también necesita la administración de estado personalizada para utilizar el estado de vista, como se describe en la sección "Descripción del código" más adelante en este tema.

El control Book que se define en el ejemplo es un control que se puede utilizar en una página Web para mostrar información sobre un libro de un catálogo. El control Book define las propiedades siguientes:

  • Author: propiedad con subpropiedades cuyo tipo es el tipo personalizado Author. El tipo Author tiene sus propias propiedades, como FirstName y LastName, que son subpropiedades de la propiedad Author.

  • BookType: propiedad simple cuyo tipo es la enumeración personalizada BookType. La enumeración BookType tiene valores como Fiction y NonFiction.

  • CurrencySymbol: propiedad simple cuyo tipo es el tipo integrado String.

  • Price: propiedad simple cuyo tipo es el tipo integrado Decimal.

  • Title: propiedad simple cuyo tipo es el tipo integrado String.

Las propiedades BookType, CurrencySymbol, Price y Title son todas propiedades simples y, por lo tanto, no necesitan ningún atributo especial para la persistencia de páginas. El marco de trabajo de páginas conserva de forma predeterminada estas propiedades como atributos en la etiqueta del control, como en el ejemplo siguiente:

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

La propiedad Author y las propiedades de la clase Author necesitan atributos en tiempo de diseño para habilitar la persistencia dentro de las etiquetas del control, como se muestra en el ejemplo siguiente:

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

El control Book almacena sus propiedades simples en el diccionario de ViewState. Sin embargo, el control Book tiene que implementar la administración de estado personalizada para que la propiedad Author administre el estado de la propiedad en las distintas devoluciones de datos.

Una implementación con calidad de producción del control Book podría definir propiedades para otros datos relacionados con el libro, como el editor y la fecha de publicación. Además, la propiedad Author se podría reemplazar por una propiedad de colección. Para obtener información sobre la implementación de una propiedad de colección, vea Ejemplo de propiedad Collection de controles Web.

Nota:

Los desarrolladores de páginas pueden deshabilitar el estado de vista para una página o para cada control de la página. Si un control necesita mantener el estado crítico en todas las devoluciones de datos para su funcionamiento interno, puede utilizar el mecanismo de estado del control definido en ASP.NET 2.0. El estado del control se describe en Ejemplo de estado de control y estado de vista.

Lista de código del control 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();
        }

    }
}

Descripción del código

Los atributos DesignerSerializationVisibilityAttribute y PersistenceModeAttribute aplicados a la propiedad Author del control Book se describen en Ejemplo de propiedad Collection de controles Web. Estos atributos son necesarios para serializar y conservar las propiedades de la clase Author.

El mecanismo de estado de vista hace referencia a la técnica empleada por ASP.NET para mantener el estado en las distintas devoluciones de datos. El mecanismo serializa el estado de una página y su árbol de control en representaciones de cadenas al final del procesamiento de la página y deserializa la cadena durante la devolución de datos. De forma predeterminada, la página envía las cadenas al explorador como campos ocultos. Para obtener más información, vea Información general sobre la administración de estados de ASP.NET.

Para administrar el estado de una propiedad simple, ésta se define como propiedad de lectura y escritura que se almacena en la propiedad ViewState del control. El control Book define sus propiedades simples (BookType, CurrencySymbol, Price y Title) de esta manera. El estado de las propiedades que se almacenan en la propiedad ViewState se administra sin que sea necesario realizar ninguna operación adicional.

Para administrar una propiedad que tiene subpropiedades, puede definir la propiedad como de sólo lectura y escribir el código para administrar el estado del objeto. Para ello, reemplace los métodos siguientes:

El tipo de la propiedad ViewState, StateBag, es un diccionario con administración de estado integrada. La clase StateBag implementa la interfaz IStateManager, que define los métodos TrackViewState, SaveViewState y LoadViewState. La clase StateBag implementa estos métodos para iniciar el seguimiento de los cambios en las propiedades de los controles tras la inicialización, guardar los elementos que se han modificado al final de la solicitud de la página y cargar el estado guardado en los elementos durante la devolución de datos. StateBag efectúa el seguimiento de los elementos marcando el elemento como modificado si éste se establece después de que el método OnInit se ejecute para una solicitud de página. Por ejemplo, si el código de la página que se ejecuta después de la inicialización de la página establece la propiedad Title del control Book, se realiza un cambio en ViewState["Title"]. En consecuencia, el valor almacenado bajo la clave "Title"en ViewState se marca como modificado. Para obtener más información, vea Información general sobre el ciclo de vida de una página ASP.NET.

El control Book define la propiedad Author como propiedad de sólo lectura e implementa la administración de estado personalizada de la manera siguiente:

  • En el método TrackViewState, el control Book guarda en primer lugar la propiedad Author inicial en una cadena y, a continuación, inicia el seguimiento de estado invocando al método TrackViewState de la clase base.

  • En el método SaveViewState, el control Book determina si la propiedad Author ha cambiado su valor inicial. Si la propiedad ha cambiado, Book guarda la propiedad Author en el diccionario ViewState utilizando la clave "Author". A continuación, el control Book invoca al método SaveViewState de la clase base. Dado que el seguimiento de estado está habilitado, el objeto Author guardado en ViewState se marca automáticamente como modificado y se guarda como parte del estado de vista de la clase base.

  • En LoadViewState, el control Book invoca en primer lugar al método LoadViewState de la clase base. Esta llamada restaura automáticamente el diccionario ViewState. A continuación, el control Book determina si el diccionario ViewState tiene un elemento almacenado bajo "Author". En ese caso, el control carga el valor del estado de vista en la propiedad Author.

El tipo Author (que se define en la lista de código siguiente) tiene un convertidor de tipos personalizado que permite almacenar una instancia de Author en el estado de vista. El convertidor de tipos convierte una instancia de Author en una cadena y viceversa. La definición de un convertidor de tipos permite establecer las subpropiedades de Author en un diseñador visual. El convertidor de tipos personalizado se describe en Ejemplo de convertidor de tipos. Los tipos que se pueden almacenar en el estado de vista están limitados por la clase LosFormatter que ASP.NET utiliza para la serialización del estado de vista. Los tipos que se serializan de manera más eficaz son String, los tipos de valores primitivos de la biblioteca de clases de .NET Framework como Boolean, Int16, Int32, Enum, Pair, Triplet, Array, ArrayList y Hashtable, y los tipos que contienen alguno de estos tipos primitivos. Además, también puede almacenar en el estado de vista los tipos personalizados para los que haya convertidores de tipos definidos, como Pair, Triplet, Array, ArrayList y Hashtable. Cuando defina la serialización del estado de vista para el control, deberá convertir los datos del control en uno de estos tipos. Si almacena en el estado de vista tipos que no son compatibles con el mecanismo de serialización del estado de vista, es posible que el control se compile, pero producirá un error en tiempo de ejecución. Por último, los tipos serializables (es decir, los tipos que implementan la interfaz ISerializable o que están marcados con SerializableAttribute) se pueden almacenar en el estado de vista, pero la serialización de estos tipos es considerablemente más lenta que la de los tipos primitivos.

El objeto de estado proporcionado por un control para la serialización es el estado de vista del control. La propiedad ViewState de un control sólo es una parte del estado de vista del control: la parte que participa automáticamente en el mecanismo de estado de vista sin que sea necesario realizar ninguna operación adicional. La clase Control implementa la lógica para guardar y cargar los elementos modificados del diccionario ViewState en sus métodos SaveViewState y LoadViewState. La otra parte o partes del estado de vista son objetos adicionales que el usuario (y la clase base del control) guarda en el estado de vista reemplazando el método SaveViewState. Cuando se reemplazan los métodos SaveViewState y LoadViewState, es necesario llamar a los métodos correspondientes de la clase base.

Lista de código de la clase Author

Al aplicar el atributo NotifyParentPropertyAttribute a las propiedades FirstName, LastName y MiddleName, y establecer el argumento del constructor del atributo en true, un diseñador visual propaga y serializa los cambios para estas propiedades en su propiedad primaria (que es una instancia de 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);
        }
    }
}

Lista de código de la enumeración 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
    }
}

Página de prueba del control Book

En el ejemplo siguiente se muestra una página .aspx que utiliza el control Book.

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

Generar y utilizar el ejemplo

Compile las clases de este ejemplo con la clase AuthorConverter que se muestra en Ejemplo de convertidor de tipos.

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

Tipos de valor en el sistema de tipos común

Referencia

IsPrimitive

Otros recursos

Desarrollar controles de servidor ASP.NET personalizados