Condividi tramite


Esempio di confronto tra stato del controllo e stato di visualizzazione

Aggiornamento: novembre 2007

Nell'esempio riportato di seguito vengono illustrate le modalità di creazione di un controllo personalizzato denominato IndexButton, che utilizza lo stato del controllo per mantenere le informazioni critiche relative allo stato su tutte le richieste di pagina. Lo stato del controllo, introdotto in ASP.NET versione 2.0, è simile allo stato di visualizzazione, ma indipendente da questo a livello funzionale. Lo sviluppatore di pagine può disattivare lo stato di visualizzazione per una pagina o per un singolo controllo per incrementare le prestazione. Lo stato del controllo, invece, non può essere disattivato. Lo stato del controllo è stato progettato per memorizzare i dati essenziali di un controllo come, ad esempio, il numero di pagina di un controllo di spostamento, che devono essere disponibili in fase di postback per consentire al controllo di funzionare anche se lo stato di visualizzazione è stato disattivato. Per impostazione predefinita, nel framework di pagina ASP.NET lo stato del controllo viene memorizzato nella pagina, nello stesso elemento nascosto in cui viene memorizzato lo stato di visualizzazione. Anche quando lo stato di visualizzazione è disattivato, o viene gestito mediante Session, lo stato del controllo si sposta tra il client e il server su un percorso di andata e ritorno nella pagina. Nel postback, ASP.NET deserializza i contenuti dell'elemento nascosto e carica lo stato del controllo in ciascun controllo registrato per lo stato del controllo.

Nota:

Utilizzare lo stato del controllo solo per quantità esigue di dati critici essenziali al funzionamento del controllo nei postback. Non utilizzare lo stato del controllo come alternativa allo stato di visualizzazione.

Nell'esempio riportato di seguito viene illustrato un controllo personalizzato che il cui stato viene salvato sia nello stato del controllo sia nello stato di visualizzazione. Nell'esempio, il controllo IndexButton deriva dalla classe Button e definisce una proprietà Index che viene salvata nello stato del controllo. Per eseguire un confronto, IndexButton definisce anche una proprietà IndexInViewState memorizzandola nel dizionario ViewState. Per visualizzare la differenza fra lo stato del controllo e lo stato di visualizzazione, utilizzare il controllo IndexButton come illustrato nella pagina ASPX presente nella sezione "Pagina di test per il controllo IndexButton" più avanti in questo argomento.

Listato di codice per il controllo 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);
                    }
                }
            }
        }

    }
}

Illustrazione del codice

L'implementazione del controllo IndexButton illustra le tre attività che occorre eseguire per consentire a un controllo di far parte di uno stato del controllo.

  • Eseguire l'override del metodo OnInit e richiamare il metodo RegisterRequiresControlState per registrare la partecipazione della pagina allo stato del controllo. Questa operazione deve essere effettuata per ogni richiesta.

  • Eseguire l'override del metodo SaveControlState per salvare i dati nello stato del controllo.

  • Eseguire l'override del metodo LoadControlState per caricare i dati dallo stato del controllo. Questo metodo chiama il metodo della classe base e ottiene il contributo di questa classe base allo stato del controllo. Se il campo indexValue è diverso da zero e lo stato del controllo della classe base non è null, la classe Pair viene utilizzata come pratica struttura di dati per salvare e ripristinare lo stato del controllo strutturato in due parti.

Pagina di test per il controllo IndexButton

Nell'esempio riportato di seguito viene illustrata una pagina in cui viene disattivato lo stato di visualizzazione impostando l'attributo EnableViewState su false nella direttiva @ Page. La pagina utilizza il controllo IndexButton e aggiunge 1 ai valori delle proprietà Index e IndexInViewState del controllo nel gestore eventi Page_Load. Le etichette della pagina visualizzano i valori delle proprietà Index e IndexInViewState.

Dato che la proprietà Index viene memorizzata nello stato del controllo, che non può essere disattivato, la proprietà Index mantiene il suo valore durante i postback aumentando di uno ogni volta che la pagina è inviata nuovamente al server. Al contrario, poiché la proprietà IndexInViewState viene memorizzata nello stato di visualizzazione, che è disattivato per la pagina, la proprietà IndexInViewState ha sempre come valore predefinito 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>

Compilazione e utilizzo dell'esempio

Per informazioni sulla compilazione e l'utilizzo degli esempi dei controlli personalizzati, vedere Generazione degli esempi dei controlli server personalizzati.

Vedere anche

Concetti

Cenni preliminari sullo stato di visualizzazione ASP.NET

Suggerimenti per la gestione dello stato di ASP.NET

Cenni preliminari sulle prestazioni

Altre risorse

Sviluppo di controlli server ASP.NET personalizzati