ASP.NET custom controls work with a ViewState dictionary, which
stores the values of its inner properties referenced by a key. The data resides
on the server so the values can be retained across postbacks, since the web is
a stateless environment. The following is an example property for a custom control.
Listing 1
public int TotalRecords
{
get
{
object o = ViewState["TotalRecords"];
return (o == null) ? 0 : (int)o;
}
set
{
ViewState["TotalRecords"] = value;
}
}
As you can see in the script, there are two main dynamic
components involved: the property name and its data type. The rest of the code
is very similar in use (with the exception of the default value returned; we will
get to that in a moment). The following script helps reduce the effort by using
a name/value collection that contains the data types/property names to use. In
this script, the name is the data type for the property and the value is the
property name. What is nice about this approach is that the CodeSmith studio
uses a friendly editor to enter the values into the system.
The property type and name values are used to generate a
list of getters and setters. It does not provide a mechanism to create
read-only properties, mainly because it is simple enough to delete the setter
from the generated code. It also does not worry about defining the custom
control class because that is usually pretty specialized. Instead, I create the
class and use the template to generate the property definitions.
This script makes use of some of the CodeSmith objects
defined in the following assembly.
Listing 2
<%@ Assembly Name="CodeSmith.CustomProperties" %>
<%@ Import Namespace="CodeSmith.CustomProperties" %>
It also defines a name/value collection which has a built-in
editor described above.
Listing 3
<%@ Property Name="PropertyTypesNames" Type="NameValueCollection" Optional="False"
Editor="CodeSmith.CustomProperties.NameValueCollectionEditor,
CodeSmith.CustomProperties" %>
The Editor attribute applies the name/value property editor;
when selecting the PropertyTypesNames property in the properties window, the
ellipsis button appears allowing the user to invoke the design-time editor.
Take a look at the editor below.
Figure 1

Using the above properties, the script takes these values
and converts them to properties as such:
Listing 4
<%
for (int i = 0; i < this.PropertyTypesNames.Count; i++)
{
string dataType = this.PropertyTypesNames[i].Key;
string name = this.PropertyTypesNames[i].Value;
%>
public <%= dataType %> <%= name %>
{
get
{
object o = ViewState["<%= name %>"];
return (o == null) ?
<%= GetDefaultDataTypeValue(dataType) %> :
(<%= dataType %>)o;
}
set { ViewState["<%= name %>"] = value; }
}
<%
}
%>
The script above is pretty simplistic. First, it gets a
local reference to the data type and name. It uses these to embed the values
into the public property definition using the <%= %> notation, which you
may be familiar with if you have done ASP scripting. It loops through, using
the name as the viewstate key, and creates a replica property as shown
previously. You may wonder what GetDefaultDataTypeValue does; this method
simply returns a default value for the data type provided, which does a little
conversion for simple types (returning zero for numeric types as the default
value, Guid.Empty for guid values, etc.). The following script renders:
Listing 5
public bool IsApproved
{
get
{
return ViewState["IsApproved "] ? ? false;
}
set
{
ViewState["IsApproved"] = value;
}
}
public string Text
{
get
{
return ViewState["Text"] ? ? string.Empty;
}
set
{
ViewState["Text"] = value;
}
}
public string Value
{
get
{
return ViewState["Value"] ? ? string.Empty;
}
set
{
ViewState["Value"] = value;
}
}
You may wonder why we do not include the class name;
usually, web control classes are complicated with the inheritance structures
they use, so this skips that part, simply meant to copy the properties into the
file.