Share via


Exemplo de Estado de Controle versus Estado de Exibição

Este exemplo mostra como criar um controle personalizado chamado IndexButton que utiliza o estado do controle para manter informações de estado críticas entre solicitações de página.O estado do controle, introduzido no ASP.NET 2.0, é semelhante ao estado de exibição, mas funcionalmente independente dele.Um desenvolvedor de página pode desativar o estado de exibição para a página ou para um controle individual pelo desempenho.No entanto, o estado do controle não pode ser desativado.o estado do controle foi projetado para armazenar dados essenciais de um controle (como o número de página de um controle de paginação) que devem estar disponíveis em um postback para habilitar o controle à função mesmo quando o estado de exibição tiver sido desativado.Por padrão, o framework de página do ASP.NET armazena o estado do controle na página no mesmo elemento oculto no qual ele armazena o estado de exibição.Mesmo se o estado de exibição estiver desativado, ou quando o estado é gerenciado usando Session, o estado do controle viaja para o cliente e volta para o servidor na página.Em um postback, o ASP.NET desserializa o conteúdo do elemento oculto e carrega o estado do controle em cada controle que está registrado para estado de controle.

Observação:

Use o estado de controle somente para pequenas quantidades de dados críticos que sejam essenciais para o controle em postagens.Não use o estado de controle como uma alternativa para o estado de exibição.

O exemplo ilustra um controle personalizado que salva o estado em ambos estado de controle e estado de exibição.No exemplo, o controle IndexButton deriva da classe Button e define uma propriedade Index que ele salva no estado do controle.Para comparação, IndexButton também define uma propriedade IndexInViewState que armazena no dicionário ViewState.Para ver a diferença entre o estado de controle e o estado de exibição, use o controle IndexButton conforme demonstrado na página .aspx listada na seção a "Página de teste para o controle IndexButton" posteriormente neste tópico.

Listagem de Código para o Controle 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);
                    }
                }
            }
        }

    }
}

Discussão de Código

A implementação do controle IndexButton ilustra as três tarefas que você deve executar para ativar um controle a participar em estado de controle:

  • Substitua o método OnInit e chame o método RegisterRequiresControlState para registrar a página de participação no estado do controle.Isso deve ser feito com cada solicitação.

  • Substitua o método SaveControlState para salvar dados no estado do controle.

  • Substitua o método LoadControlState para carregar os dados do estado do controle.Este método chama o método da classe base e obtém a contribuição da classe base para o estado do controle.Se o campo indexValue não for zero e o estado do controle da classe base não for nulo, a classe Pair é usada como uma estrutura de dados conveniente para salvar e restaurar o estado do controle de duas partes.

Página de Teste para o Controle IndexButton

O exemplo a seguir ilustra uma página que desativa o estado de exibição definindo o atributo EnableViewState para false na diretiva @ Page.A página usa o controle IndexButton e adiciona 1 aos valores das propriedades Index e IndexInViewState do controle no manipulador de eventos Page_Load.Os rótulos na página exibem os valores das propriedades Index e IndexInViewState.

Como a propriedade Index é armazenada no estado do controle, que não pode ser desativado, a propriedade Index mantém seu valor em um postback e aumenta um sempre que a página é postada de volta para o servidor.Por outro lado, porque a propriedade IndexInViewState é armazenada no estado de exibição, que é desativado para a página, a propriedade IndexInViewState sempre tem o seu valor padrão de zero.

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

Construindo e Usando o Exemplo

Para obter informações sobre a compilação e uso dos exemplos de controles personalizados, consulte Construindo os Exemplos de Controle de Servidor Personalizado.

Consulte também

Conceitos

Visão geral do estado de exibição do ASP.NET

Recomendações sobre Gerenciamento de Estado do ASP.NET

Visão geral sobre desempenho

Outros recursos

Desenvolvendo Controles Personalizados ASP.NET Server