Пример управления состоянием настраиваемого свойства
Обновлен: Ноябрь 2007
В этом примере показывается, как определить свойство серверного элемента управления, тип которого сам реализует управление собственным состоянием. Элемент управления BookNew в этом примере определяет свойство Author, тип которого, StateManagedAuthor, сам выполняет управление собственным состоянием, реализуя интерфейс IStateManager. Тип StateManagedAuthor описан в разделе Пример управления состоянием пользовательского типа.
Элемент управления BookNew в этом разделе аналогичен элементу управления Book, описанному в разделе Пример использования свойств серверного веб-элемента управления, показывающем, как определять свойство с вложенными свойствами. Разница между элементами управления BookNew и Book заключается в том, что тип свойства Author в элементе управления BookNew делегирует управление состоянием свойства Author методам управления состоянием типа StateManagedAuthor свойства. Напротив, элемент управления Book явно управляет состоянием своего свойства Author.
Методы, используемые для реализации управления состоянием (TrackViewState, SaveViewState и LoadViewState) описаны ниже в данном разделе, в подразделе «Рассмотрение кода».
Пример кода для элемента управления BookNew
Следующий код представляет собой пример элемента управления BookNew. Управление состоянием выполняется с помощью свойства Author элемента управления BookNew и методов управления состоянием (TrackViewState, SaveViewState и LoadViewState) класса StateManagedAuthor.
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), _
DefaultProperty("Title"), _
ToolboxData("<{0}:BookNew runat=""server""> </{0}:BookNew>") _
> _
Public Class BookNew
Inherits WebControl
Private authorValue As StateManagedAuthor
< _
Bindable(True), _
Category("Appearance"), _
DefaultValue(""), _
Description("The name of the author."), _
DesignerSerializationVisibility( _
DesignerSerializationVisibility.Content), _
PersistenceMode(PersistenceMode.InnerProperty) _
> _
Public Overridable ReadOnly Property Author() _
As StateManagedAuthor
Get
If authorValue Is Nothing Then
authorValue = New StateManagedAuthor
If IsTrackingViewState Then
CType(authorValue, IStateManager).TrackViewState()
End If
End If
Return authorValue
End Get
End Property
< _
Bindable(True), _
Category("Appearance"), _
DefaultValue(BookType.NotDefined), _
Description("Fiction or Not") _
> _
Public Overridable Property BookType() As BookType
Get
Dim t As Object = ViewState("BookType")
If t Is Nothing Then t = BookType.NotDefined
Return CType(t, BookType)
End Get
Set(ByVal value As BookType)
ViewState("BookType") = value
End Set
End Property
< _
Bindable(True), _
Category("Appearance"), _
DefaultValue(""), _
Description("The symbol for the currency."), _
Localizable(True) _
> _
Public Overridable Property CurrencySymbol() As String
Get
Dim s As String = CStr(ViewState("CurrencySymbol"))
If s Is Nothing Then s = String.Empty
Return s
End Get
Set(ByVal value As String)
ViewState("CurrencySymbol") = value
End Set
End Property
< _
Bindable(True), _
Category("Appearance"), _
DefaultValue("0.00"), _
Description("The price of the book."), _
Localizable(True) _
> _
Public Overridable Property Price() As Decimal
Get
Dim p As Object = ViewState("Price")
If p Is Nothing Then p = Decimal.Zero
Return CType(p, Decimal)
End Get
Set(ByVal value As Decimal)
ViewState("Price") = value
End Set
End Property
< _
Bindable(True), _
Category("Appearance"), _
DefaultValue(""), _
Description("The title of the book."), _
Localizable(True) _
> _
Public Overridable Property Title() As String
Get
Dim s As String = CStr(ViewState("Title"))
If s Is Nothing Then s = String.Empty
Return s
End Get
Set(ByVal value As String)
ViewState("Title") = value
End Set
End Property
Protected Overrides Sub Render(ByVal writer As HtmlTextWriter)
MyBase.AddAttributesToRender(writer)
writer.RenderBeginTag(HtmlTextWriterTag.Table)
writer.RenderBeginTag(HtmlTextWriterTag.Tr)
writer.RenderBeginTag(HtmlTextWriterTag.Td)
writer.WriteEncodedText(Title)
writer.RenderEndTag()
writer.RenderEndTag()
writer.RenderBeginTag(HtmlTextWriterTag.Tr)
writer.RenderBeginTag(HtmlTextWriterTag.Td)
writer.WriteEncodedText(Author.ToString())
writer.RenderEndTag()
writer.RenderEndTag()
writer.RenderBeginTag(HtmlTextWriterTag.Tr)
writer.RenderBeginTag(HtmlTextWriterTag.Td)
writer.WriteEncodedText(BookType.ToString())
writer.RenderEndTag()
writer.RenderEndTag()
writer.RenderBeginTag(HtmlTextWriterTag.Tr)
writer.RenderBeginTag(HtmlTextWriterTag.Td)
writer.Write(CurrencySymbol)
writer.Write(" ")
writer.Write(String.Format("{0:F2}", Price))
writer.RenderEndTag()
writer.RenderEndTag()
writer.RenderEndTag()
End Sub
#Region "state management"
Protected Overrides Sub LoadViewState( _
ByVal savedState As Object)
Dim p As Pair = TryCast(savedState, Pair)
If p IsNot Nothing Then
MyBase.LoadViewState(p.First)
CType(Author, IStateManager).LoadViewState(p.Second)
Return
End If
MyBase.LoadViewState(savedState)
End Sub
Protected Overrides Function SaveViewState() As Object
Dim baseState As Object = MyBase.SaveViewState
Dim thisState As Object = Nothing
If authorValue IsNot Nothing Then
thisState = _
CType(authorValue, IStateManager).SaveViewState()
End If
If thisState IsNot Nothing Then
Return New Pair(baseState, thisState)
Else
Return baseState
End If
End Function
Protected Overrides Sub TrackViewState()
If authorValue IsNot Nothing Then
CType(Author, IStateManager).TrackViewState()
End If
MyBase.TrackViewState()
End Sub
#End Region
End Class
End Namespace
// BookNew.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),
DefaultProperty("Title"),
ToolboxData("<{0}:BookNew runat=\"server\"> </{0}:BookNew>")
]
public class BookNew : WebControl
{
private StateManagedAuthor authorValue;
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("The name of the author."),
DesignerSerializationVisibility(
DesignerSerializationVisibility.Content),
PersistenceMode(PersistenceMode.InnerProperty)
]
public virtual StateManagedAuthor Author
{
get
{
if (authorValue == null)
{
authorValue = new StateManagedAuthor();
if (IsTrackingViewState)
{
((IStateManager)authorValue).TrackViewState();
}
}
return authorValue;
}
}
[
Bindable(true),
Category("Appearance"),
DefaultValue(BookType.NotDefined),
Description("Fiction or Not"),
]
public virtual BookType BookType
{
get
{
object t = ViewState["BookType"];
return (t == null) ? BookType.NotDefined : (BookType)t;
}
set
{
ViewState["BookType"] = value;
}
}
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("The symbol for the currency."),
Localizable(true)
]
public virtual string CurrencySymbol
{
get
{
string s = (string)ViewState["CurrencySymbol"];
return (s == null) ? String.Empty : s;
}
set
{
ViewState["CurrencySymbol"] = value;
}
}
[
Bindable(true),
Category("Appearance"),
DefaultValue("0.00"),
Description("The price of the book."),
Localizable(true)
]
public virtual Decimal Price
{
get
{
object price = ViewState["Price"];
return (price == null) ? Decimal.Zero : (Decimal)price;
}
set
{
ViewState["Price"] = value;
}
}
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("The title of the book."),
Localizable(true)
]
public virtual string Title
{
get
{
string s = (string)ViewState["Title"];
return (s == null) ? String.Empty : s;
}
set
{
ViewState["Title"] = value;
}
}
protected override void Render(HtmlTextWriter writer)
{
base.AddAttributesToRender(writer);
writer.RenderBeginTag(HtmlTextWriterTag.Table);
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.WriteEncodedText(Title);
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.WriteEncodedText(Author.ToString());
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.WriteEncodedText(BookType.ToString());
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.Write(CurrencySymbol);
writer.Write(" ");
writer.Write(String.Format("{0:F2}", Price));
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderEndTag();
}
#region state management
protected override void LoadViewState(object savedState)
{
Pair p = savedState as Pair;
if (p != null)
{
base.LoadViewState(p.First);
((IStateManager)Author).LoadViewState(p.Second);
return;
}
base.LoadViewState(savedState);
}
protected override object SaveViewState()
{
object baseState = base.SaveViewState();
object thisState = null;
if (authorValue != null)
{
thisState = ((IStateManager)authorValue).SaveViewState();
}
if (thisState != null)
{
return new Pair(baseState, thisState);
}
else
{
return baseState;
}
}
protected override void TrackViewState()
{
if (authorValue != null)
{
((IStateManager)authorValue).TrackViewState();
}
base.TrackViewState();
}
#endregion
}
}
Рассмотрение кода
Элемент управления BookNew демонстрирует модель реализации свойств, типы которых управляют своим собственным состоянием, реализуя интерфейс IStateManager. При изучении кода для элемента управления BookNew в этом разделе может оказаться полезным также изучить код для типа StateManagedAuthor, который является типом свойства Author элемента управления BookNew. Пример кода для StateManagedAuthor приведен в разделе Пример управления состоянием пользовательского типа.
Элемент управления BookNew определяет свойство Author как свойство только для чтения, хранящееся в закрытом поле типа StateManagedAuthor. В методе доступа к свойству Author, если закрытое поле, соответствующее свойству, является значением null (Nothing в Visual Basic), то элемент управления BookNew назначает этому закрытому полю новый объект StateManagedAuthor. Если для элемента управления BookNew запущено отслеживание состояния, BookNew инициирует отслеживание состояния для вновь созданного объекта StateManagedAuthor, вызывая метод TrackViewState объекта. Дополнительные сведения об отслеживании см. в разделе Пример использования свойств серверного веб-элемента управления.
Свойство Author участвует в управлении состоянием, вызывая методы IStateManager объекта StateManagedAuthor из своих собственных методов управления состоянием: TrackViewState, SaveViewState и LoadViewState.
В переопределенном методе TrackViewState элемент управления BookNew вызывает метод TrackViewState базового класса и метод TrackViewState объекта StateManagedAuthor, соответствующего свойству Author.
В переопределенном методе SaveViewState элемент управления BookNew вызывает метод SaveViewState базового класса и метод SaveViewState объекта StateManagedAuthor, соответствующего свойству Author. Если у свойства Author есть состояние для сохранения, то метод SaveViewState элемента управления BookNew возвращает объект Pair, содержащий состояние базового класса и свойства Author. Если у свойства Author нет состояния для сохранения, то метод возвращает только состояние, возвращаемое вызовом метода SaveViewState базового класса. В зависимости от количества настраиваемых свойств, вносящих свой вклад в состояние, разработчик должен возвратить из метода SaveViewState объекты типа Pair, Triplet или Array. Это упрощает извлечение различных частей сохраненного состояния в методе LoadViewState. В этом случае используется класс Pair, так как существуют два элемента: состояние базового класса и состояние Author.
В переопределенном методе LoadViewState элемент управления BookNew реализует операцию, противоположную реализуемой в методе LoadViewState. BookNew загружает состояние в базовый класс и в свойство Author, или, если у свойства Author нет состояния для сохранения, BookNew загружает состояние только в базовый класс. Разработчик всегда должен вызывать метод LoadViewState базового класса, даже если сохраненное состояние является значением null (Nothing в Visual Basic), так как базовый класс, если у него отсутствует состояние для сохранения, мог реализовать другую логику в этом методе.
Тестовая страница и элемент управления BookNew
В следующем примере показана ASPX-страница, использующая элемент управления BookNew.
<%@ Page Language="C#"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
void Button_Click(object sender, EventArgs e)
{
BookNew1.Author.FirstName = "Bob";
BookNew1.Author.LastName = "Kelly";
BookNew1.Title = "Contoso Stories";
BookNew1.Price = 39.95M;
Button1.Visible = false;
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>
BookNew test page
</title>
</head>
<body>
<form id="Form1" runat="server">
<aspSample:BookNew ID="BookNew1" Runat="server"
BorderStyle="Solid" BorderWidth="1px" Title="Tailspin Stories"
CurrencySymbol="$" BackColor="#FFE0C0" Font-Names="Tahoma"
Price="16" BookType="Fiction">
<Author FirstName="Judy" LastName="Lew" />
</aspSample:BookNew>
<br />
<asp:Button ID="Button1" OnClick="Button_Click"
Runat="server" Text="Change" />
<asp:Button ID="Button2" Runat="server" Text="Refresh" />
<br />
<br />
<asp:HyperLink ID="Hyperlink1" href="BookNewTest.aspx"
Runat="server">
Reload Page</asp:HyperLink>
</form>
</body>
</html>
Построение и использование примера
Скомпилируйте элемент управления BookNew с классом StateManagedAuthor и классом StateManagedAuthorConverter, описанным в разделе Пример управления состоянием пользовательского типа.
Дополнительные сведения о сборке элемента управления и его использования на странице см. в разделе Примеры связывания пользовательского серверного элемента управления.
См. также
Основные понятия
Пример управления состоянием пользовательского типа
Пример использования свойств серверного веб-элемента управления
Другие ресурсы
Разработка пользовательских серверных элементов управления ASP.NET