Anatomy of a Server Control
Part 2 - Maintaining State
by Uncle Chutney
Table of Contents:
|
|
Introduction: This is the second
of a series, which begins with "Part 1 - A Simple Control3."
This series builds on principles outlined in my "ASP.Net Fundamentals1"
article and my "The Life and Times of a Server Control2"
article. If you're unfamiliar with how ASP.Net works, you should begin by
reading those. Part 13 demonstrated how a Server Control renders an HTML interface, by using the Render() method of System.Web.UI.Control. Now we're going to expand on that, and talk about Maintaining State using ViewState. For our example Control, we will duplicate System.Web.UI.HtmlControls.HtmlInputText. This fairly simple Server Control renders an HTML text box (<input type="text"...>) in the page. The text box can retain its' value between PostBacks. Other than that, it can fire one event of its own: The ServerChange Event. This Event is fired when the value of the text box is changed programmatically on the server. Other than that, it's a pretty straightforward HTML text box. It has a few other properties which are specific to itself, such as MaxLength (maximum number of characters to enter), Size (Number of rows to display in the window), and Value (the text contained in the box). And that's about it! Requirements: This demonstration was built with the Microsoft Visual Basic.Net language, using Microsoft's Visual Studio.Net. While these examples could fairly easily be written in Notepad, and converted in order to prevent the necessity of compilation, it is recommended that you use the same tools. About HtmlInputText: The HtmlInputText class is derived (inherited) from System.Web.UI.HtmlControls.HtmlControl class, as are all other HtmlControls. Let's begin by looking at this class, which is derived from System.Web.UI.Control: All classes which inherit System.Web.UI.HtmlControl are referred to as "HtmlControls." These are classes which do not much more than render HTML in a page. Certain HTML properties for HtmlControls can be accessed programmatically, and they do have the ability to maintain state across PostBacks. A plain HTML object in an ASP.Net Page Template can be converted to an Html Control simply by adding a "runat=server" attribute to the tag. Let's take a look at the Properties, Methods, and Events which all HtmlControls share in common first. HtmlControl Properties: All HtmlControls share all of the Properties of System.Web.UI.Control4, plus the following:
HtmlControl Methods: All HtmlControls share all the Methods of a System.Web.UI.Control5. No additional Methods exist. HtmlControl Events: All HtmlControls share all the Events of a System.Web.UI.Control6. No additional Events exist. HtmlInputText also derives from an abstract (MustInherit) Base class called System.Web.UI.HtmlControls.HtmlInputControl. HtmlInputControl is derived from HtmlControl, and is the common class for all HtmlControls that render "input" types of form fields, such as "input type=text", "input type=button", "input type=file" etc. The following are the Properties, Methods, and Events which all HtmlInputControls share in common: HtmlInputControl Properties: All HtmlInputControls share all the Properties of HtmlControl, plus the following:
HtmlInputControl Methods: All HtmlInputControls share all the Methods of HtmlControl. No additional Methods exist. HtmlInputControl Events: All HtmlInputControls share all the Events of HtmlControl. No additional Events exist. Now, let's examine the Properties, Methods, and Events which the HtmlInputText class adds to these: HtmlInputText Properties: The HtmlInputText Control shares all Properties of HtmlInputControl, plus the following:
HtmlInputText Methods: The HtmlInputText Control shares all Properties of HtmlControl. No additional Methods exist. HtmlInputText Events: The HtmlInputText Control shares all Properties of HtmlControl, plus the following:
Maintaining State: Apart from rendering an Interface, maintaining State is the second most common type of thing that a Server Control can do. This is particularly important with ASP.Net because of the programming model of the WebForm. A WebForm posts back to itself. It can have form fields which must retain their value between PostBacks (otherwise, the user would have to keep filling them back in). Therefore, maintaining State is quite often necessary. In this example, the HtmlInputText Control renders a text box on the client-side HTML form. If the textbox resides in a page which posts back to itself, we want it to retain the same Value it had before it was posted back. As you should recall from my first article1, HTTP is stateless, and State is emulated by passing data back and forth between the client and server. This is done using the hidden "__VIEWSTATE" field in the form. This demonstration will show how this is achieved using the ViewState class, and the IPostBackDataHandler interface. Building DemoControls.HtmlInputText: I departed somewhat from the actual object model in this case, because I wanted to demonstrate how to maintain state in a Control. Since System.Web.UI.HtmlControls.HtmlInputText inherits System.Web.UI.HtmlControls.HtmlInputControl, and System.Web.UI.HtmlControls.HtmlInputControl already maintains the state of the Value property, it wouldn't make a very good example if I just let all that state maintenance remain encapsulated in the Base Class. So, instead, I inherited System.Web.UI.Control, and rebuilt all the underlying properties for myself. In addition, for the sake of the clarity of this demonstration, I omitted several Base Class properties, methods, etc. From System.Web.UI.HtmlControl, I omitted the Attributes collection and the Style property. I did leave in the one Event which the System.Web.UI.HtmlControls.HtmlInputText Control fires: The ServerChange Event7. While this demonstration is not about raising events, it is very simple to do so, and I left it in as an example. Because this sample does somewhat more than the last, you will find quite a few inline comments in the code regarding the "how" and "why" of what is being done. The following is the complete class file for the DemoControls.HtmlInputText class: Imports System.Web.UI Public Class
HtmlInputText
' ** The IPostBackDataHandler interface provides the ability for Controls
' ** This is the EventHandler that is fired when the Value property changes.
' ** As this is a property which can be set in the Designer,
Public ReadOnly Property TagName() As String
Public ReadOnly Property Name() As String
' ** This property emulates the Type property shared by all
' ** Here is how the Value property maintains state:
' ** A textbox can have a MaxLength set or not. Because of this, we
initialize
' ** As this is a property which can be set in the Designer,
' ** As usual, the Render Method does the real work of rendering the HTML
' ** Because the developer can assign any String value to the Type property,
If _Type.ToLower = "password" Then strType = "password"
' ** Because the Disabled property is a Boolean value, we use Boolean logic
' ** This is the first of the 2 IPostBackDataHandler methods required by the
interface.
If Value <> postCollection(postDataKey) Then
' ** If the LoadPostData Function returns True, this Sub is fired.
RaiseEvent ServerChange(Me, EventArgs.Empty) End Class Notes: As you can see, to maintain state for this control, I had to do 2 things. First, I created the Value property of the Control as a Public property with accessor methods which Get and Set the ViewState for this property. Secondly, I implemented IPostBackDataHandler, and wrote code in the LoadPostData function that updates the ViewState for this property on PostBack. I also demonstrated raising an event from a Control, by adding the ServerChange Event for this one. To do this, I added a Public Property ServerChange, which is of the type "EventHandler" and raised the Event when the LoadPostData Sub found that the Value of the Control had changed. There were a few other properties which I added. We can see that if a Property's state should be maintained, we need to create accessor methods to tie it to the ViewState. Also, if a Property's state is maintained via hard-coded Template values, we create a Private field, and tie the Public Property's accessor methods to that field. When adding Properties to a Control, make sure that they are initialized in order to prevent data type mismatch errors. Once I had compiled this Control, I added it to the Toolbox in Visual Studio.Net, and dragged it onto an ASPX page (Default.aspx):
I set the Value property to "Test" and was now ready to add my CodeBehind: Public Class _Default
Protected WithEvents Text1 As DemoControls.HtmlInputText
#End Region
Private Sub Text1_ServerChange(ByVal sender As Object, ByVal e As
System.EventArgs) _ Note that I added no additional code to the page, other than the Event Handler for the ServerChange Event. Now I was ready to test it in a browser:
The top part represents the way the page looked initially. I typed in the "ing" and submitted the form, which resulted in the portion seen in the bottom, displaying the Event Handler's message. Conclusions: By building an HtmlInputText Control, we have demonstrated how a Server Control maintains state, by mapping properties to ViewState, and implementing IPostBackDataHandler to update the state of the Control during PostBack. In addition, we have provided a simple demonstration of a Server Control which raises an Event. |
|
Footnotes:
1. See "ASP.Net Fundamentals" 2. See "The Life and Times of a Server Control" 3. See "Anatomy of a Server Control Part 1: A Simple Control" 4. See "The Life and Times of a Server Control" 'Control Properties' section 5. See "The Life and Times of a Server Control" 'Control Methods' section 6. See "The Life and Times of a Server Control" 'Control Events' section 7. The ServerChange Event is fired whenever the Value property of the text box changes |


