Any custom control will have a whole bunch of properties – some private and a lot of them public. When you have public properties in a custom control, you (as the control developer) are expecting the Page developer (the one using your custom control) to set them via the Properties box or from the code.
Using ViewState for storing properties
Once these public properties are set, you want to get these values between the postbacks so that you can set them back again. In order to do this, you use the ViewState property.
Code Listing 1. Normal code for get and set for a property
#region Public Properties
/// <summary>
/// The HTML Text in the text box of the AJAXWrite.
/// </summary>
[Category("AJAXWrite")]
[DefaultValue("")]
public string Text
{
get
{
String s = (String)ViewState["Text"];
return ((s == null) ? String.Empty : s);
}
set
{
ViewState["Text"] = value;
}
}
Dealing with the ViewState via generic functions
As shown the above example, you save the property value in the ViewState and when it’s needed, you get it back from there. The above code can be made generic as the functions shown below. This is how AJAXControlToolkit gets and sets the public properties from one single place.
Code Listing 2. Take out the ViewState code and put it in separate functions
#region Generic Property Getter and Setter
/// <summary>
/// Returns the property stored in the ViewState.
/// </summary>
/// <typeparam name="V">Type of the property: String, Integer, etc.</typeparam>
/// <param name="propertyName">Name of the property</param>
/// <param name="nullValue">The value to return in case the property value is null</param>
/// <returns>The value of the property stored in the ViewState</returns>
protected V GetPropertyValue<V>(string propertyName, V nullValue)
{
if (ViewState[propertyName] == null)
{
return nullValue;
}
return (V)ViewState[propertyName];
}
/// <summary>
/// Saves the property value in the ViewState
/// </summary>
/// <typeparam name="V">Type of the property</typeparam>
/// <param name="propertyName">Name of the property</param>
/// <param name="value">Value of the property</param>
protected void SetPropertyValue<V>(string propertyName, V value)
{
ViewState[propertyName] = value;
}
#endregion
With the above code, you don’t have to explicitly check for null value in each of these public properties. You can pass a value to the GetPropertyValue method to return back in case the property is null.
So, now the getters and setters for your public properties look like the following (you can do any additional pre or post processing here as well)
Code Listing 3. Using the generic getter/setter functions
#region Public Properties
/// <summary>
/// The HTML Text in the text box of the AJAXWrite.
/// </summary>
[Bindable(true)]
[Category("AJAXWrite")]
[DefaultValue("")]
public string Text
{
get
{
return GetPropertyValue<String>("Text", String.Empty);
}
set
{
SetPropertyValue<String>("Text", value);
}
}
#endregion
As you can see from Figure 1, ViewState is derived from System.Web.UI.StateBag class and behaves like a dictionary (since the StateBag implements IDictionary in addition to other interfaces). The saved property values from ViewState can be obtained like it is an associative array in JavaScript. In the case, the save Text property has “This is a test” as its value.
Figure 1. ViewState from the GetPropertyValue

Non-generic Wrappers
The above generic functions take type-insensitive – meaning, your property can be of any type – String, Integer, etc. If you look in the AJAXControlToolkit, you will also find separate functions for storing string, int, and bool property values in the ViewState. However, it is advisable not to use this – instead use the generic function directly.
Code Listing 4. Non-generic functions that call the generic functions underneath
[Obsolete("Use GetPropertyValue<V> instead")]
protected string GetPropertyStringValue(string propertyName)
{
return GetPropertyValue<string>(propertyName, "");
}
[Obsolete("Use SetPropertyValue<V> instead")]
protected void SetPropertyStringValue(string propertyName, string value)
{
SetPropertyValue<string>(propertyName, value);
}
[Obsolete("Use GetPropertyValue<V> instead")]
protected int GetPropertyIntValue(string propertyName)
{
return GetPropertyValue<int>(propertyName, 0);
}
[Obsolete("Use SetPropertyValue<V> instead")]
protected void SetPropertyIntValue(string propertyName, int value)
{
SetPropertyValue<int>(propertyName, value);
}
[Obsolete("Use GetPropertyValue<V> instead")]
protected bool GetPropertyBoolValue(string propertyName)
{
return GetPropertyValue<bool>(propertyName, false);
}
[Obsolete("Use SetPropertyValue<V> instead")]
protected void SetPropertyBoolValue(string propertyName, bool value)
{
SetPropertyValue<bool>(propertyName, value);
}