Export (0) Print
Expand All

Custom Property State Management Example

This example shows how to define a server control property whose type implements its own state management. The BookNew control in the example defines an Author property whose type, StateManagedAuthor, performs its own state management by implementing the IStateManager interface. The StateManagedAuthor type is described in Custom Type State Management Example.

The BookNew control in this topic is similar to the Book control described in Server Control Properties Example, which shows how to define a property that has subproperties. The difference between the BookNew and Book controls is that the type of the Author property in BookNew delegates state management of the Author property to the state management methods of the property's StateManagedAuthor type. In contrast, the Book control explicitly manages the state of its Author property.

The methods used to implement state management (TrackViewState, SaveViewState, and LoadViewState) are described in the "Code Discussion" section later in this topic.

The following code listing of the BookNew control. State management is performed by the Author property of BookNew and the state management methods (TrackViewState, SaveViewState, and LoadViewState) of the StateManagedAuthor class.


// 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

    }
}


The BookNew control demonstrates the pattern for implementing properties whose types manage their own state by implementing the IStateManager interface. While examining the code for the BookNew control in this topic, you might find it useful to also examine the code for the StateManagedAuthor type, the type of the BookNew control's Author property. The code listing for StateManagedAuthor is in the Custom Type State Management Example topic.

BookNew defines the Author property as a read-only property, stored in a private field of type StateManagedAuthor. In the Author property accessor, if the private field corresponding to the property is null (Nothing in Visual Basic), BookNew assigns a new StateManagedAuthor object to the private field. If BookNew has started tracking state, BookNew initiates state tracking on the newly created StateManagedAuthor object by invoking the object's TrackViewState method. For more information about tracking, see Server Control Properties Example.

The Author property participates in state management by calling the IStateManager methods of the StateManagedAuthor object from its own state management methods: TrackViewState, SaveViewState, and LoadViewState.

In the overridden TrackViewState method, BookNew calls the TrackViewState method of the base class and the TrackViewState method of the StateManagedAuthor object that corresponds to the Author property.

In the overridden SaveViewState method, BookNew invokes the SaveViewState method of the base class and the SaveViewState method of the StateManagedAuthor object that corresponds to the Author property. If the Author property has state to save, the BookNew control's SaveViewState method returns a Pair object that contains the state of the base class and of the Author property. If the Author property does not have state to save, the method returns only the state returned by the SaveViewState call to the base class. Based on the number of custom properties that contribute state, you should return objects of type Pair, Triplet, or Array from SaveViewState. This enables you to retrieve the different parts of the saved state more easily in the LoadViewState method. In this case, the Pair class is used, because there are two items, the base class state and the Author state.

In the overridden LoadViewState method, BookNew implements the inverse of the operations that it implemented in the LoadViewState method. BookNew loads state into the base class and into the Author property, or, if the Author property did not have state to save, BookNew loads state into only the base class. You should always call the LoadViewState method of the base class, even if the saved state is null (Nothing in Visual Basic), because the base class might have implemented other logic in this method when it does not have state to restore.

The following example shows an .aspx page that uses the BookNew control.


<%@ 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" NavigateUrl="BookNewTest.aspx" 
        Runat="server">
        Reload Page</asp:HyperLink>
    </form>
  </body>
</html>


Compile the BookNew control with the StateManagedAuthor class and the StateManagedAuthorConverter class described in Custom Type State Management Example.

For more information about building the control and using it in a page, see Building the Custom Server Control Examples.

Community Additions

ADD
Show:
© 2014 Microsoft