Sdílet prostřednictvím


Beispiel für den Vergleich zwischen Steuerelementzustand und Ansichtszustand

Aktualisiert: November 2007

Dieses Beispiel zeigt, wie Sie ein benutzerdefiniertes Steuerelement mit dem Namen IndexButton erstellen, das mithilfe des Steuerelementzustands wichtige Zustandsinformationen über mehrere Seitenanforderungen hinweg speichert. Zwar ähnelt der in ASP.NET 2.0 eingeführte Steuerelementzustand dem Ansichtszustand, in funktioneller Hinsicht ist er jedoch vom Ansichtszustand unabhängig. Der Ansichtszustand kann vom Seitenentwickler für eine Seite oder für ein einzelnes Steuerelement aus Leistungsgründen deaktiviert werden. Dies trifft für den Steuerelementzustand jedoch nicht zu. Der Steuerelementzustand wurde zum Speichern wichtiger Steuerelementdaten (z. B. die Seitennummer eines Pagersteuerelements) entwickelt, die für ein Postback zur Verfügung stehen müssen, damit das Steuerelement auch bei deaktiviertem Ansichtszustand funktioniert. Standardmäßig speichert das ASP.NET-Seitenframework den Steuerelementzustand im gleichen ausgeblendeten Element der Seite, in dem auch der Ansichtszustand gespeichert wird. Selbst bei deaktiviertem Ansichtszustand oder wenn der Zustand mit Session verwaltet wird, findet eine Übermittlung des Steuerelementzustands an den Client und wieder zurück zum Server statt. Beim Postback deserialisiert ASP.NET den Inhalt des ausgeblendeten Elements und lädt den Steuerelementzustand in jedes Steuerelement, das für den Steuerelementzustand registriert ist.

1whwt1k7.alert_note(de-de,VS.90).gifHinweis:

Verwenden Sie den Steuerelementzustand nur für geringe Mengen wichtiger Daten, die für das Steuerelement über mehrere Postbacks hinweg eine entscheidende Rolle spielen. Verwenden Sie den Steuerelementzustand nicht als Ersatz für den Ansichtszustand.

Das Beispiel zeigt ein benutzerdefiniertes Steuerelement, das den Zustand sowohl im Steuerelementzustand als auch im Ansichtszustand speichert. Im Beispiel leitet sich das IndexButton-Steuerelement von der Button-Klasse ab. Es definiert eine Index-Eigenschaft, die im Steuerelementzustand gespeichert wird. Zum Vergleich: IndexButton definiert auch eine IndexInViewState-Eigenschaft, die aber im ViewState-Wörterbuch gespeichert wird. Um den Unterschied zwischen Steuerelementzustand und Ansichtszustand zu verstehen, verwenden Sie das IndexButton-Steuerelement wie in der ASPX-Seite veranschaulicht, die im Abschnitt "Testseite für das IndexButton-Steuerelement" weiter unten in diesem Thema aufgeführt wird.

Codeauflistung für das IndexButton-Steuerelement

' 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);
                    }
                }
            }
        }

    }
}

Codeerläuterung

Die Implementierung des IndexButton-Steuerelements zeigt die drei Schritte, die zum Aktivieren eines Steuerelements für die Teilnahme am Steuerelementzustand erforderlich sind:

  • Überschreiben der OnInit-Methode und Aufrufen der RegisterRequiresControlState-Methode, um die Seite für die Teilnahme am Steuerelementzustand zu registrieren. Dies muss bei jeder Anforderung geschehen.

  • Überschreiben der SaveControlState-Methode, um Daten im Steuerelementzustand zu speichern.

  • Überschreiben der LoadControlState-Methode, um Daten aus dem Steuerelementzustand zu laden. Diese Methode ruft die Basisklassenmethode auf und ruft den Beitrag der Basisklasse zum Steuerelementzustand ab. Wenn das indexValue-Feld nicht 0 und der Steuerelementzustand der Basisklasse nicht NULL ist, wird die Pair-Klasse als Datenstruktur verwendet, um den zweiteiligen Steuerelementzustand zu speichern und wiederherzustellen.

Testseite für das IndexButton-Steuerelement

Das folgende Beispiel zeigt eine Seite, die den Ansichtszustand deaktiviert, indem sie in der @ Page-Direktive das EnableViewState-Attribut auf false festlegt. Die Seite verwendet das IndexButton-Steuerelement und erhöht den Wert der Index-Eigenschaft und den Wert der IndexInViewState-Eigenschaft des Steuerelements im Page_Load-Ereignishandler um jeweils 1. Die Bezeichnungen in der Seitenanzeige stellen die Werte der Index-Eigenschaft und der IndexInViewState-Eigenschaft dar.

Da die Index-Eigenschaft im nicht deaktivierbaren Steuerelementzustand gespeichert wird, behält die Index-Eigenschaft bei einem Postback ihren Wert bei und wird jedes Mal um 1 erhöht, wenn die Seite zurück an den Server gesendet wird. Im Unterschied dazu ist der Standardwert der IndexInViewState-Eigenschaft immer 0, da die IndexInViewState-Eigenschaft im (für die Seite deaktivierten) Ansichtszustand gespeichert ist.

<%@ 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 runat="server">
    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" runat="server">
    <title>IndexButton test page</title>
  </head>
  <body>
    <form id="form1" runat="server">
        Click the button:
        <aspSample:IndexButton Text="IndexButton" 
            ID="IndexButton1" runat="server"/>
      <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 runat="server">
  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" runat="server">
    <title>IndexButton test page</title>
  </head>
  <body>
    <form id="form1" runat="server">
        Click the button:
        <aspSample:IndexButton Text="IndexButton" 
            ID="IndexButton1" runat="server"/>
      <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>

Erstellen und Verwenden des Beispiels

Weitere Informationen über das Kompilieren und Verwenden der benutzerdefinierten Beispielsteuerelemente finden Sie unter Erstellen der Beispiele für benutzerdefinierte Serversteuerelemente.

Siehe auch

Konzepte

Übersicht über den ASP.NET-Ansichtszustand

Empfehlungen zur ASP.NET-Zustandsverwaltung

Übersicht über die Leistung

Weitere Ressourcen

Entwickeln von benutzerdefinierten ASP.NET-Serversteuerelementen