State Management
Previusly in the last post we saw the web custom controls attributes. We can interactive with the web user control through its attributes.
To implement a custom control, you have to implement a class in procedural lenguages as C# or VB.NET that derives from a base class such as Control. Every server control directly or indirectly derives from the Control base class.
The base class Control provides server controls with the infrastructure they need to operate as a server control in the ASP.NET framework. One of these infrastructural methods is a method named Render. This method is where a server control generates or renders its HTML markup text.
For example, if you wish to put a html table into the page, you need to use the next code or similar code:
namespace CustomComponents
{
public class CustomControl : Control
{
protected override void Render (HtmlTextWriter writer)
{
writer.Write("<table style='border: solid 1px black; width:250' id='myTable'> ");
writer.Write("<tr><td> Table content</td></tr> ");
writer.Write("</table> ");
base.Render(writer);
}
}
}
- The compilers don't catch the typing errors. For example, the following error:
Writer.Write("<spon/>");
- You must emit different HTML markup text for different browsers.
For resolve all these problems exists HtmlTextWriterTag, HtmlTextWriterAttribute and HtmlTextWriterStyle enumerations. For example, HtmlTextWriterTag.Span corresponds to the HTML tag, HtmlTextWriterAttribute.Id corresponds to the id HTML attribute and HtmlTextWriterStyle.Width corresponds to the width CSS style attribute.
These enumerations provide the following benefits:
- We can benefit from the compiler type-checking capability to avoid problems associated with string manipulations.
- Visual Studio provides IntelliSense support for these enumerations.
- The ASP.NET Framework comes with two versions of these enumerations, the HTML 4.0 standard and the HTML 3.2 standard version. The custom control doesn't have to do extra work to create different HTML markup texts for different browsers, the ASP.NET Framework will automatically use the right versions.
Now, with the attibute enumerations our code would be like this:
namespace CustomComponents
{
public class CustomControl : Control
{
protected override void Render(HtmlTextWriter writer)
{
writer.AddStyleAttribute(HtmlTextWriterStyle.BorderStyle, "solid");
writer.AddStyleAttribute(HtmlTextWriterStyle.BorderColor, "black");
writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, "1");
writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "250px");
writer.AddAttribute(HtmlTextWriterAttribute.Id, "myTable");
writer.RenderBeginTag(HtmlTextWriterTag.Table);
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
writer.Write("Table content");
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderEndTag();
base.Render(writer);
}
}
}
Now, if the properties of our custom control need to maintain their values across page postbacks, you have to take extra steps.
The Control class exposes a collection property named ViewState. This collection automatically saves and loads its content across page postbacks without any coding on your part. You should use this collection as the backing store for those properties of your custom control that need to mantain their values across page postbacks.
The properties of your custom controls as items of type System.Object regardless of their real types, and returns these values as items of type System.Object. That is why the getter of each property must convert (type cast) the item that it retrieves from the ViewState collection to the real type of the property before you returns the value.
When it comes to storing objects to ViewState we must keep the following two important things in mind:
- ViewState is optimized to convert certain types such as System.String, System.Int32, System.Boolean, System.Drawing.Color, System.Unit and HashTable, Array and ArrayList of Int32, Boolean, Color and Unit values. If the custom control needs to store other types to ViewState, we should write a custom type converter that optimized to convert the custom type to its string representation.
- Because the string representations of the objects we add to ViewState are stored on the ASP.NET page, we must store only necesary information to ViewState to reduce the size of the ASP.NET page.
Also, we have the control state, introduced in ASP.NET version 2.0. If you wish you can disable view state for the page or for an individual control for performance. However, control state cannot be disabled. On postback, ASP.NET deserializes the contents of the hidden element and loads control state into each control that is registered for control state.
An sample of control state:
protected override void LoadControlState(object savedState)
{
object[] objState = (object[])savedState;
base.LoadControlState(objState[0]);
this.EnableRowClickEvent = (bool)objState[1];
this.EnableRowDoubleClickEvent = (bool)objState[2];
this.ActivateRollOverColor = (bool)objState[3];
}
protected override object SaveControlState()
{
object[] objR = {
base.SaveControlState(),
this.EnableRowClickEvent,
this.EnableRowDoubleClickEvent,
this.ActivateRollOverColor
};
return objR;
}
Resources
Professional ASP.NET 2.0 Server Control and Component Development
Dr. Shahram Khosravi
ISBN-13: 978-0-471-79350-2
http://www.wiley.com/WileyCDA/WileyTitle/productCd-0471793507.html
http://msdn.microsoft.com/es-es/library/system.web.ui.htmltextwriter(VS.80).aspx
#1 Re: How to create custom controls in ASP.NET part 2 of 3
Just like ViewState, dynamic controls seem to be fodder for much debate, and a source of many confusing issues. This article will be the first of a multi-part series to detail just about everything you could ever want to know about how Dynamic Controls