Сравнительный пример использования состояния элемента управления и состояния просмотра

Visual Studio 2010

Обновлен: Ноябрь 2007

Данный пример показывает, как создать пользовательский элемент управления под названием IndexButton, который использует состояние элемента управления для сохранения важной информации о состоянии в промежутках между запросами страницы. Состояние элемента управления, появившееся в ASP.NET версии 2.0, похоже на состояние просмотра, но функционально оно не зависит от состояния просмотра. Разработчик страницы может отключить состояние просмотра для страницы или для отдельного элемента управления для повышения производительности. В то же время состояние элемента управления отключить невозможно. Состояние элемента управления предназначено для хранения важных данных об элементе управления (например, номера страницы для элемента управления страничного навигатора), которые должны быть доступны при обратной передаче, чтобы элемент управления мог работать даже в том случае, если состояние просмотра отключено. По умолчанию платформа веб-страниц ASP.NET сохраняет состояние элемента управления на странице в том же скрытом элементе, в котором хранится состояние просмотра. Даже если состояние просмотра отключено или же поддерживается с помощью свойства Session, состояние элемента управления на странице может передаваться между клиентом и сервером в обоих направлениях. При обратной передаче ASP.NET десериализует содержимое скрытого элемента и загружает состояние элемента управления в каждый элемент управления, который зарегистрирован в состоянии элемента управления.

1whwt1k7.alert_note(ru-ru,VS.100).gifПримечание.

Состояние элемента управления следует использовать только для малых количеств важной информации, которая существенна для элемента управления при обратной передаче. Не используйте состояние элемента управления в качестве альтернативы состоянию просмотра.

В данном примере показан пользовательский элемент управления, который сохраняет состояние элемента управления и состояния просмотра. В данном примере элемент управления IndexButton является производным от класса Button; в нем определяется свойство Index, которое он сохраняет в состоянии элемента управления. Для сравнения в IndexButton также определяется свойство IndexInViewState, которое сохраняется в словаре ViewState. Чтобы увидеть разницу между состоянием элемента управления и состоянием просмотра, используйте элемент управления IndexButton, как показано на странице ASPX, приведенной ниже в разделе "Тестовая страница для элемента управления IndexButton".

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

    }
}


Реализация элемента управления IndexButton демонстрирует три задачи, которые необходимо выполнить для ввода элемента управления в состав состояния элемента управления:

  • Переопределите метод OnInit и вызовите метод RegisterRequiresControlState для регистрации на странице для участия в состоянии элемента управления. Это необходимо делать при каждом запросе.

  • Переопределите метод SaveControlState для сохранения данных в состоянии элемента управления.

  • Переопределите метод LoadControlState для загрузки данных из состояния элемента управления. Этот метод вызывает метод базового класса и извлекает дополнение базового класса к состоянию элемента управления. Если поле indexValue имеет ненулевое значение и состояние элемента управления базового класса также не пусто, то класс Pair используется в качестве удобной структуры данных для сохранения и восстановления двусоставного состояния элемента управления.

В следующем примере приведена страница, на которой состояние просмотра отключено посредством присвоения атрибуту EnableViewState значения falseв директиве @ Page. На странице используется элемент управления IndexButton; к значениям свойств Index и IndexInViewState элемента управления в обработчике событий Page_Load прибавляется 1. Подписи на странице отображают значения свойств Index и IndexInViewState.

Так как свойство Index хранится в состоянии элемента управления, которое нельзя отключить, то свойство Index сохраняет свое значение при обратной передаче и увеличивается на единицу при каждой последующей обратной передаче страницы на сервер. Напротив, свойство IndexInViewState хранится в состоянии просмотра, которое отключено на странице, поэтому свойство IndexInViewState всегда имеет значение по умолчанию, равное нулю.

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


Дополнительные сведения о компиляции и использовании примеров пользовательских элементов управления см. в разделе Примеры связывания пользовательского серверного элемента управления.

Показ: