Сравнительный пример использования состояния элемента управления и состояния просмотра
Обновлен: Ноябрь 2007
Данный пример показывает, как создать пользовательский элемент управления под названием IndexButton, который использует состояние элемента управления для сохранения важной информации о состоянии в промежутках между запросами страницы. Состояние элемента управления, появившееся в ASP.NET версии 2.0, похоже на состояние просмотра, но функционально оно не зависит от состояния просмотра. Разработчик страницы может отключить состояние просмотра для страницы или для отдельного элемента управления для повышения производительности. В то же время состояние элемента управления отключить невозможно. Состояние элемента управления предназначено для хранения важных данных об элементе управления (например, номера страницы для элемента управления страничного навигатора), которые должны быть доступны при обратной передаче, чтобы элемент управления мог работать даже в том случае, если состояние просмотра отключено. По умолчанию платформа веб-страниц ASP.NET сохраняет состояние элемента управления на странице в том же скрытом элементе, в котором хранится состояние просмотра. Даже если состояние просмотра отключено или же поддерживается с помощью свойства Session, состояние элемента управления на странице может передаваться между клиентом и сервером в обоих направлениях. При обратной передаче ASP.NET десериализует содержимое скрытого элемента и загружает состояние элемента управления в каждый элемент управления, который зарегистрирован в состоянии элемента управления.
Примечание. |
---|
Состояние элемента управления следует использовать только для малых количеств важной информации, которая существенна для элемента управления при обратной передаче. Не используйте состояние элемента управления в качестве альтернативы состоянию просмотра. |
В данном примере показан пользовательский элемент управления, который сохраняет состояние элемента управления и состояния просмотра. В данном примере элемент управления IndexButton является производным от класса Button; в нем определяется свойство Index, которое он сохраняет в состоянии элемента управления. Для сравнения в IndexButton также определяется свойство IndexInViewState, которое сохраняется в словаре ViewState. Чтобы увидеть разницу между состоянием элемента управления и состоянием просмотра, используйте элемент управления IndexButton, как показано на странице ASPX, приведенной ниже в разделе "Тестовая страница для элемента управления IndexButton".
Листинг кода для элемента управления 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);
}
}
}
}
}
}
Рассмотрение кода
Реализация элемента управления IndexButton демонстрирует три задачи, которые необходимо выполнить для ввода элемента управления в состав состояния элемента управления:
Переопределите метод OnInit и вызовите метод RegisterRequiresControlState для регистрации на странице для участия в состоянии элемента управления. Это необходимо делать при каждом запросе.
Переопределите метод SaveControlState для сохранения данных в состоянии элемента управления.
Переопределите метод LoadControlState для загрузки данных из состояния элемента управления. Этот метод вызывает метод базового класса и извлекает дополнение базового класса к состоянию элемента управления. Если поле indexValue имеет ненулевое значение и состояние элемента управления базового класса также не пусто, то класс Pair используется в качестве удобной структуры данных для сохранения и восстановления двусоставного состояния элемента управления.
Тестовая страница для элемента управления IndexButton
В следующем примере приведена страница, на которой состояние просмотра отключено посредством присвоения атрибуту EnableViewState значения falseв директиве @ Page. На странице используется элемент управления IndexButton; к значениям свойств Index и IndexInViewState элемента управления в обработчике событий Page_Load прибавляется 1. Подписи на странице отображают значения свойств Index и IndexInViewState.
Так как свойство Index хранится в состоянии элемента управления, которое нельзя отключить, то свойство Index сохраняет свое значение при обратной передаче и увеличивается на единицу при каждой последующей обратной передаче страницы на сервер. Напротив, свойство IndexInViewState хранится в состоянии просмотра, которое отключено на странице, поэтому свойство IndexInViewState всегда имеет значение по умолчанию, равное нулю.
<%@ 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>
Построение и использование примера
Дополнительные сведения о компиляции и использовании примеров пользовательских элементов управления см. в разделе Примеры связывания пользовательского серверного элемента управления.
См. также
Основные понятия
Общие сведения о состоянии представления ASP.NET
Рекомендации по управлению состоянием ASP.NET
Общие сведения о производительности
Другие ресурсы
Разработка пользовательских серверных элементов управления ASP.NET