

ASP.NET Custom Controls
If you’re not happy with the way that an ASP.NET WebForm control works, write your own!
In ASP.NET you can create a WebForm control of your own just by inheriting from some other WebForm control and writing the code to make the control do what you want. While that’s true of most objects in the .NET environment, there are some special considerations in writing an object to work on a WebForm in ASP.NET. In this article I’ll start by showing you how to easily extend any WebForm control. Further down the road I’ll show you how to handle ASP.NET specific issues like writing out the HTML for your code and integrating with the ASP.NET ViewState. Regardless of how much you do or don’t modify your control, your Custom Control will be treated like any other WebForm control: Developers will be able to add to their Visual Studio.NET toolbox, drag the control onto a form, and manipulate the control from both the Visual Studio IDE and from their application’s code.

Specifying a Custom Control
I’ll begin this journey by adding a method of my own to an ASP.NET control. This is probably the typical situation for most control developers: You like the functionality of some control but there’s some little thing about it that annoys you. For instance, with the ASP.NET ListBox, if I’m not loading the ListBox from a database, I have to add items to the control one at a time by using the Items collection’s Add method. This code adds some Canadian cities to a list box:
Me.ListBox1.Items.Add(“Regina”)
Me.ListBox1.Items.Add(“Ottawa”)
Me.ListBox1.Items.Add(“Winipeg”)
This isn’t the most awkward code in the world, but I would appreciate a method like this that would let me add all of the items in a single statement:
Me.PHVListBox1.AddList (“Regina”, “Ottawa”, “Winnipeg”)

Creating the base control
To extend a control you begin by creating a WebForm Custom Control. You can do this one of two ways:
1. Add a custom control to the ASP.NET Web project that you intend to use the control in
2. Create a new custom control project
I recommend the second method. A custom control added to your Web project is compiled into your project’s executable file, along with all of the other code in the project. However, a separate custom control project is compiled into a separate DLL file. By isolating your control into a separate file, it’s considerably easier to re-use your custom control in other projects. In addition, if you end up developing a set of controls that are often used together or share some common code, you can build these controls in the same custom control project. This creates a custom control library of useful objects that you can use in any project. Don’t worry that creating separate custom control packages makes it difficult to install your application. If you build your installation package in Visual Studio .NET, any application that uses your controls will automatically be distributed with a copy of the control library.
However, if you’re confident that the only place that you will use your new control is in one project, just add a custom control to your project. This is actually the simplest way to get started: just select Project > Add New Item > Web Custom Control to put a Custom Control to your project.
For my second method (to create a separate custom control project), in Visual Studio .NET, first open the ASP.NET project where you intend to use the control. Then, from the File menu, select Add New Project. In the dialog box that appears, select the language you intend to use (e.g. Visual Basic Projects) and Web Control Library. When you click the Open button a second project is added to your Visual Studio .NET solution along with your ASP.NET project. This makes it easy to switch between the code in your new control and the ASP.NET application that uses the control. Your project’s files will be kept in a subfolder of your Web project folder in the Visual Studio Projects folder.

Adding the control
The Web Control Library project that’s created for you will contain a default control file called WebCustomControl1. I find the default settings in this file more awkward than helpful, so I recommend that you delete it. Then go to your Project menu and select Add New Item to bring up the Add New Item dialog. On this dialog, select Web Custom Control, give your control a name, and click the Open button.
The reason that I do this is that the name of your Custom Control appears several times in your code. Using Add Existing Item causes the name of your control to be inserted in all the right places for you. Here’s a Visual Basic.NET example from a control that I called BetterListBox.
<DefaultProperty("Text"), ToolboxData(
"<{0}:BetterListBox runat=server></{0}:BetterListBox>")> _
Public Class BetterListBox _
Inherits System.Web.UI.WebControls.WebControl
The attributes inside the pointy brackets hold some important information for your control. In my example, the DefaultProperty attribute establishes that the control’s Text property is the default for the control. The ToolBoxData attribute controls the tag added to your ASPX page when the control is dragged onto your WebForm (but not the HTML that will go to the browser—I’ll discuss that later). ToolBoxData also controls the name that appears when your control is added to the Visual Studio.NET toolbox. The name in the Class line is the name that your object will be known by to the applications that use it.
If you are extending an existing control, I would now delete most the code inside of your user control. For Visual Basic.NEt, that means deleting everything between “Inherits” line and the “End Class” line; For C#, I delete all the code between the curly braces that enclose the class. This code can be useful if you are creating a control from scratch as I’ll show later.
Extending a control
With a clean slate, I’m now ready to add the code to create my better ListBox. This may seem like a daunting task when you think of all of the methods, properties, and events that a ListBox supports. Fortunately, you don’t have to write all that code yourself. Instead, you’ll inherit most of that functionality. In Visual Basic.NET, that means rewriting this line in the WebForm file from this
Inherits System.Web.UI.WebControls.WebControl
to this
Inherits System.Web.UI.WebControls.ListControl
In C#, you must rewrite the class module declaration, changing it from this
public class BetterListBox: System.Web.UI.WebControls.WebControl
to this
public class BetterListBox: System.Web.UI.WebControls.ListControl
These changes cause all the ListBox’s existing functionality to be inherited so that you only need to add any new methods or properties that you want (or override any existing methods whose behavior you want to change). At this point, writing your code looks very much like writing the code in any application. You can even access all the methods and properties of the underlying object that you are inheriting from. In Visual Basic .NET, the underlying object is known as MyBase; in C# it’s called base.
For instance, to create my LoadList routine, I would use this code in Visual Basic.NET:
Public Sub LoadList(strList As String)
Dim strValues() As String
Dim strValue As String
strValues = strList.Split(",")
For Each strValue in strValues
MyBase.Items.Add(strValue.Trim)
Next
End Sub
In C#, I would use this code:
public void LoadList(string strList)
{string[] strValues;
strValues = strList.Split(",".ToCharArray());
foreach (string strValue in strValues)
{
base.Items.Add(strValue.Trim());
}
}
In both cases, I’m using the Items collection of the Listbox to add new items to the ListBox.

Using Your Control
Once you’ve written your control, you’ll need to compile it (select Build > Build projectname from the Visual Studio.NET menus). To test your control, you’ll need to add the control to a Web page. If you followed my advice and have a solution with both an ASP.NET and a Custom Control project in it, testing isn’t hard to do. First, right-mouse click on the ToolBox and pick Add/Remove Items. The Customize Toolbox dialog appears. Clicking on the Browse button will let you navigate to the DLL created from your Custom Control. Select the DLL and click on the Open button to add all the controls in the library to the Visual Studio .NET ToolBox. Before leaving the Customize Toolbox dialog you can uncheck any of the controls in the library that you don’t want in your toolbox.
Once the control is in your ToolBox, you can add it to a WebForm like any other control: Just drag it from the ToolBox onto the form. Visual Studio.NET will generate the necessary support code for the host page’s code to work with the control. For instance, after adding my BetterListBox control to a Web page, I call my LoadList routine like this in VB.NET:
Me.BetterListBox1.AddList (“Regina”, “Ottawa”, “Winnipeg”)

Writing your own HTML
But what if you want to create a completely new control? In that case you wouldn’t rewrite the line that inherits your functionality: leave it as WebControl. This causes you to inherit just the base functionality common to all WebForm controls. You have more work to do but you can have your control do whatever you want. The first thing that you’ll need to consider is how your Custom Control will create its user interface.
All custom controls display their user interface by writing HTML out to the WebForm page that they are used on. When ASP.NET needs the control’s HTML, ASP.NET calls the control’s Render event. You must override this method with the code to create the HTML that is your control’s UI.
The Render method is passed an HtmlTextWriter that is used to write out the control’s HTML using the text writer’s Write method. As an example, you might decide that you’ve always wanted to have a custom control that generates the HTML to display text both bold and italicized. I’ll call this control BoldItalic and the Render method for my control would look like this:
Protected Overrides Sub Render( _
ByVal output As System.Web.UI.HtmlTextWriter)
output.Write(“<b><i>” & _text & “</i></b>”)
End Sub
I didn’t choose the variable _text at random—the default code that I recommended that you normally delete from the WebUserControl includes a Text property that stores its value in a variable called _text. Code that used my control on an ASP.NET page would look like this:
Me.BoldItalic1.Text = “Hello, World”
The default code for the Text property will move “Hello, World” into the _text variable. ASP.NET will ensure that my Render method at the appropriate moment to add my HTML to the page.
You can, of course, add your own properties and methods writing as much code as you want. However, you can use a number of attributes to handle tasks that you might otherwise bet tempted to write code for. A look at the start of the Text property that is automatically added to your control is informative. In VB.NET, the code looks like this:
<Bindable(True), Category("Appearance"), DefaultValue("")> _
Property [Text]() As String
In C#, it looks like this:
[Bindable(true), Category("Appearance"), DefaultValue("")]
public string Text
These attributes take care of a lot of work for you:
· The Bindable attribute indicates that this property can be used in databinding
· The Category attribute sets what area of the control’s Property List this property should appear in (assuming that you display your Property List in category order)
· The DefaultValue attribute establishes the value of the property if the property is never set to a value by the host application.
I think that the DefaultValue attribute really shows the power of attribute-based programming: don’t write code—just tell the compiler what behavior you want.
Updating the ViewState
The problem with defining a property in a Web environment is that Web applications don’t maintain state. Some browser will request your page and code on the page will execute and set your control’s property. ASP.NET will then call your control’s Render method to write out its HTML to the page. However, once the HTML is sent to the browser, the ASP.NET page and your custom control are removed from memory. Whatever your control’s property was set to by the code in the page, that information is now lost—unless you do something about it.
To handle this, WebForm pages have the ViewState where controls can store all the information they need to recreate themselves. However, it’s your responsibility to both store the information that you need in the ViewState and to retrieve it when necessary. For instance, to save and retrieve the text property in the ViewState you would use code like this in VB.NET:
MyBase.ViewState("MyText") = _text
_text = CType(MyBase.ViewState("MyText"), String)
In C#, the equivalent code is
base.ViewState["MyText"] = _text;
_text = (String) base.ViewState["MyText"];
In both sets of code, the first line establishes an entry in the ViewState called MyText and sets it to the value of the _text variable. The second line retrieves the value in the MyText entry and updates the _text variable with it. To remove an item from the ViewState set the item to Nothing (in Visual Basic .NET) or null (in C#).
Typically, you’ll save data to the ViewState in the property’s Set portion. In other words, every the value of the property is changed, you’ll save it in the ViewState. Deciding when to retrieve data from the ViewState is more complicated because you want to avoid retrieving a property’s value from the ViewState if the property has already been set by code from the host page.
One other issue is key: Deciding what to put in the ViewState. You should put only as much data as you need in the ViewState. Data added to the ViewState is mime-encoded and stored in a string that is inserted into the Web page. As a result, this data is sent to the browser as part of the page, so the more data that you put in the ViewState, the more bloated the page is. The ViewState data is also sent back to the server when the user presses the Submit button, doubling the impact of extra data.
In addition, mime-encoding only barely counts as a form of encryption: you don’t want to put anything in the ViewState that you want kept secret.
I’ve given you the essentials of creating a custom control of your very own in this article. You can extend an existing control (avoiding the problems of writing your own Render methods and updating the ViewState) or you can create a control from scratch. It’s an interesting journey that you’re starting on and one that doesn’t really have an end—but you can create some powerful tools that will help you on the way.
