ASP.NET

Controls and View State

Before leaving rendered controls, let's take a look at the issue of control state. If you go back to some of the classic ASP examples from earlier tutorials, you may notice something disconcerting about the way some of the controls, such as selection boxes, work. After you select something in the combo box and make a round-trip to the server, by the time the response gets back the controls (for example, selection controls) have lost their state. Recall that the Web is all about making snapshots of the server's state and displaying them using a browser. We're essentially trying to perform stateful UI development over a disconnected protocol.

ASP.NET server-side controls include a facility for holding on to a page's visual state-it's a property in the Page named ViewState, and you can easily access it any time you need. ViewState is a dictionary (a name-value collection) that stores any serializable object.

Most ASP.NET server-side controls manage their visual state by storing and retrieving items in the ViewState. For example, a selection control might maintain the index of the selected item between posts so that the control knows which item gets the <selected> tag.

The entire state of a page is encoded in a hidden field between posts. For example, if you browse to an ASPX page and view the source code coming from the server, you'll see the ViewState come through as a BASE 64-encoded byte stream.

To get a feel for how ViewState works, add some code to keep track of the palindromes that have been viewed through the control.

Using View State

  1. Open the PalindromeCheckerRenderedControl.cs file.

  2. Add an ArrayList to the control to hold the viewed palindromes. Update the Text property's setter to store text in the view state if the text is a palindrome.

    public class PalindromeCheckerRenderedControl : WebControl
    {
       public event EventHandler PalindromeFound; // public event
    
    
          ArrayList alPalindromes = new ArrayList();
    
    
       private string text;
    
       [Bindable(true)]
       [Category("Appearance")]
       [DefaultValue("")]
       public string Text
       {
          get
          {
             return text;
          }
          set
          {
             text = value;
             this.alPalindromes =
                      (ArrayList)this.ViewState["palindromes"];
             if (this.alPalindromes == null)
             {
                this.alPalindromes = new ArrayList();
             }
             if(this.CheckForPalindrome()) {
                if (PalindromeFound != null)
                {
                   PalindromeFound(this, EventArgs.Empty);
                }
                alPalindromes.Add(text);
             }
             this.ViewState.Add("palindromes", alPalindromes);
          }
       }
    
  3. Add a method to render the palindrome collection as a table and update the Render method to render the viewed palindromes.

    protected void RenderPalindromesInTable(HtmlTextWriter output)
    {
       output.AddAttribute(HtmlTextWriterAttribute.Width, "50%");
       output.AddAttribute(HtmlTextWriterAttribute.Border, "1");
       output.RenderBeginTag(HtmlTextWriterTag.Table); //<table>
    
       foreach (string s in this.alPalindromes)
       {
          output.RenderBeginTag(HtmlTextWriterTag.Tr); // <tr>
          output.AddAttribute(HtmlTextWriterAttribute.Align, "left");
          output.AddStyleAttribute(HtmlTextWriterStyle.FontSize, "medium");
          output.AddStyleAttribute(HtmlTextWriterStyle.Color, "blue");
          output.RenderBeginTag(HtmlTextWriterTag.Td); // <td>
          output.Write(s);
          output.RenderEndTag(); // </td>
          output.RenderEndTag(); // </tr>
       }
       output.RenderEndTag(); // </table>
    }
    protected override void Render(HtmlTextWriter output)
    {
       if (this.CheckForPalindrome())
       {
          output.Write("This is a palindrome: <br>");
          output.RenderBeginTag(HtmlTextWriterTag.Font);
          output.AddStyleAttribute(HtmlTextWriterStyle.Color, "blue");
          output.RenderBeginTag(HtmlTextWriterTag.B);
          output.Write(Text);
          output.RenderEndTag(); // bold
          output.RenderEndTag(); // font
       } else {
          output.Write("This is NOT a palindrome: <br>");
          output.RenderBeginTag(HtmlTextWriterTag.Font);
          output.AddStyleAttribute(HtmlTextWriterStyle.Color, "red");
          output.RenderBeginTag(HtmlTextWriterTag.B);
          output.Write(Text);
          output.RenderEndTag(); // bold
          output.RenderEndTag(); // font
       }
       output.Write("<br>");
       RenderPalindromesInTable(output);
    }
    
  4. Build and run the application. When you surf to the page holding the palindrome checker, you should see the previously found palindromes appearing in the table:

    Graphic