Поделиться через


Пример управления состоянием настраиваемого свойства

Обновлен: Ноябрь 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("&nbsp")
            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("&nbsp;");
            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