Compartir a través de


Ejemplo de estado de control y estado de vista

Actualización: noviembre 2007

En este ejemplo se muestra cómo crear un control personalizado denominado IndexButton que utiliza el estado del control para mantener información de estado crucial en las distintas solicitudes de la página. El estado del control, que es nuevo en ASP.NET versión 2.0, es similar al estado de vista pero funcionalmente es independiente de éste. Con objeto de mejorar rendimiento, el desarrollador de páginas puede deshabilitar el estado de vista para la página o para un control en concreto. Sin embargo, el estado del control no se puede deshabilitar. El estado del control se ha diseñado para almacenar datos esenciales del control (como el número de página del elemento de paginación del control) que deben estar disponibles en la devolución de datos para permitir que el control funcione aunque se haya deshabilitado el estado de vista. De forma predeterminada, el marco de trabajo de las páginas ASP.NET almacena el estado del control en la página, en el mismo elemento oculto en el que almacena el estado de vista. Aun cuando se deshabilite el estado de vista o cuando el estado se administre utilizando Session, el estado del control va al cliente y vuelve al servidor en la página. En la devolución de datos, ASP.NET deserializa el contenido del elemento oculto y carga el estado del control en cada uno de los controles registrados para el estado del control.

Nota:

Utilice el estado del control sólo para pequeñas cantidades de datos críticos que sean esenciales para el control en las distintas devoluciones de datos. No debe utilizar el estado del control como alternativa al estado de vista.

En el ejemplo se muestra un control personalizado que guarda el estado, tanto en el estado del control como en el estado de vista. En el ejemplo, el control IndexButton se deriva de la clase Button y define una propiedad Index que se guarda en el estado del control. A modo de comparación, IndexButton también define una propiedad IndexInViewState que se almacena en el diccionario de ViewState. Para ver la diferencia existente entre el estado del control y el estado de vista, utilice el control IndexButton que se muestra en la página .aspx de la sección "Página de prueba del control IndexButton", situada más adelante en este tema.

Lista de código del control IndexButton

' IndexButton.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), _
    ToolboxData("<{0}:IndexButton runat=""server""> </{0}:IndexButton>") _
    > _
    Public Class IndexButton
        Inherits Button
        Private indexValue As Integer

        < _
        Bindable(True), _
        Category("Behavior"), _
        DefaultValue(0), _
        Description("The index stored in control state.") _
        > _
        Public Property Index() As Integer
            Get
                Return indexValue
            End Get
            Set(ByVal value As Integer)
                indexValue = value
            End Set
        End Property

        < _
        Bindable(True), _
        Category("Behavior"), _
        DefaultValue(0), _
        Description("The index stored in view state.") _
        > _
        Public Property IndexInViewState() As Integer
            Get
                Dim obj As Object = ViewState("IndexInViewState")
                If obj Is Nothing Then obj = 0
                Return CInt(obj)
            End Get
            Set(ByVal value As Integer)
                ViewState("IndexInViewState") = value
            End Set
        End Property

        Protected Overrides Sub OnInit(ByVal e As EventArgs)
            MyBase.OnInit(e)
            Page.RegisterRequiresControlState(Me)
        End Sub

        Protected Overrides Function SaveControlState() As Object
            ' Invoke the base class's method and
            ' get the contribution to control state
            ' from the base class.
            ' If the indexValue field is not zero
            ' and the base class's control state is not null,
            ' use Pair as a convenient data structure
            ' to efficiently save 
            ' (and restore in LoadControlState)
            ' the two-part control state
            ' and restore it in LoadControlState.

            Dim obj As Object = MyBase.SaveControlState()

            If indexValue <> 0 Then
                If obj IsNot Nothing Then
                    Return New Pair(obj, indexValue)
                Else
                    Return indexValue
                End If
            Else
                Return obj
            End If
        End Function

        Protected Overrides Sub LoadControlState(ByVal state As Object)
            If (state IsNot Nothing) Then
                Dim p As Pair = TryCast(state, Pair)
                If p IsNot Nothing Then
                    MyBase.LoadControlState(p.First)
                    indexValue = CInt(p.Second)
                Else
                    If (TypeOf (state) Is Integer) Then
                        indexValue = CInt(state)
                    Else
                        MyBase.LoadControlState(state)
                    End If
                End If
            End If
        End Sub

    End Class
End Namespace
// IndexButton.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),
    ToolboxData("<{0}:IndexButton runat=\"server\"> </{0}:IndexButton>")
    ]
    public class IndexButton : Button
    {
        private int indexValue;

        [
        Bindable(true),
        Category("Behavior"),
        DefaultValue(0),
        Description("The index stored in control state.")
        ]
        public int Index
        {
            get
            {
                return indexValue;
            }
            set
            {
                indexValue = value;
            }
        }

        [
        Bindable(true),
        Category("Behavior"),
        DefaultValue(0),
        Description("The index stored in view state.")
        ]
        public int IndexInViewState
        {
            get
            {
                object obj = ViewState["IndexInViewState"];
                return (obj == null) ? 0 : (int)obj;
            }
            set
            {
                ViewState["IndexInViewState"] = value;
            }
        }

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            Page.RegisterRequiresControlState(this);
        }

        protected override object SaveControlState()
        {
            // Invoke the base class's method and
            // get the contribution to control state
            // from the base class.
            // If the indexValue field is not zero
            // and the base class's control state is not null,
            // use Pair as a convenient data structure
            // to efficiently save 
            // (and restore in LoadControlState)
            // the two-part control state
            // and restore it in LoadControlState.

            object obj = base.SaveControlState();

            if (indexValue != 0)
            {
                if (obj != null)
                {
                    return new Pair(obj, indexValue);
                }
                else
                {
                    return (indexValue);
                }
            }
            else
            {
                return obj;
            }
        }

        protected override void LoadControlState(object state)
        {
            if (state != null)
            {
                Pair p = state as Pair;
                if (p != null)
                {
                    base.LoadControlState(p.First);
                    indexValue = (int)p.Second;
                }
                else
                {
                    if (state is int)
                    {
                        indexValue = (int)state;
                    }
                    else
                    {
                        base.LoadControlState(state);
                    }
                }
            }
        }

    }
}

Descripción del código

La implementación del control IndexButton muestra las tres tareas que se deben realizar para habilitar un control de modo que participe en el estado del control:

  • Reemplace el método OnInit e invoque al método RegisterRequiresControlState para que se registre en la página a fin de participar en el estado del control. Esta operación se debe realizar con cada solicitud.

  • Reemplace el método SaveControlState para guardar los datos en el estado del control.

  • Reemplace el método LoadControlState para cargar los datos del estado del control. Este método llama al método de la clase base y obtiene la contribución de dicha clase al estado del control. Si el valor del campo indexValue no es cero y el estado del control de la clase base no es nulo, la clase Pair se utiliza como estructura de datos adecuada para guardar y restaurar el estado del control dividido en dos partes.

Página de prueba del control IndexButton

En el ejemplo siguiente se muestra una página que deshabilita el estado de vista al establecer el atributo EnableViewState en false en la directiva @ Page. La página utiliza el control IndexButton y agrega uno (1) a los valores de las propiedades Index e IndexInViewState del control en el controlador de eventos Page_Load. Las etiquetas de la página muestran los valores de las propiedades Index e IndexInViewState.

Dado que la propiedad Index se almacena en el estado del control, que no se puede deshabilitar, la propiedad Index conserva su valor en la devolución de datos y aumenta en uno cada vez que la página se devuelve al servidor. Por el contrario, dado que la propiedad IndexInViewState se almacena en el estado de vista, que está deshabilitado para la página, la propiedad IndexInViewState siempre tiene su valor predeterminado de cero.

<%@ Page Language="VB" Trace="true" EnableViewState="false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script >
    Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
        Label1.Text = IndexButton1.Index.ToString()
        Label2.Text = IndexButton1.IndexInViewState.ToString()
        IndexButton1.Index += 1
        IndexButton1.IndexInViewState += 1
    End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
  <head id="Head1" >
    <title>IndexButton test page</title>
  </head>
  <body>
    <form id="form1" >
        Click the button:
        <aspSample:IndexButton Text="IndexButton" 
            ID="IndexButton1" />
      <br />
      <br />
      The value of the Index property of IndexButton is:<br />
      <asp:Label ID="Label1" Runat="server" Text="Label">
      </asp:Label>
      <br />
      <br />
      The value of the IndexInViewState property of IndexButton is:
      <br />
      <asp:Label ID="Label2" Runat="server" Text="Label">
      </asp:Label>
      <br />
    </form>
  </body>
</html>
<%@ Page Language="C#" Trace="true" EnableViewState="false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script >
  void Page_Load(object sender, EventArgs e)
  {
    Label1.Text = (IndexButton1.Index++).ToString();
    Label2.Text = (IndexButton1.IndexInViewState++).ToString();
  }
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
  <head id="Head1" >
    <title>IndexButton test page</title>
  </head>
  <body>
    <form id="form1" >
        Click the button:
        <aspSample:IndexButton Text="IndexButton" 
            ID="IndexButton1" />
      <br />
      <br />
      The value of the Index property of IndexButton is:<br />
      <asp:Label ID="Label1" Runat="server" Text="Label">
      </asp:Label>
      <br />
      <br />
      The value of the IndexInViewState property of IndexButton is:
      <br />
      <asp:Label ID="Label2" Runat="server" Text="Label">
      </asp:Label>
      <br />
    </form>
  </body>
</html>

Generar y utilizar el ejemplo

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

Información general sobre el estado de vista en ASP.NET

Recomendaciones de administración de estado de ASP.NET

Información general sobre el rendimiento

Otros recursos

Desarrollar controles de servidor ASP.NET personalizados