Creating Web Custom Controls with Visual Studio.NET...
Part I: Overview and Composite Controls

Web custom controls provide a more flexible, as well as more complex, alternative to user controls. Custom controls are the subject matter of this series of two articles.


By: Chris Sully Date: June 30, 2003 Download the code.

Introduction

Web custom controls provide a more flexible, as well as more complex, alternative to user controls. Custom controls are the subject matter of this series of two articles but first we'll shortly place them in context by looking at the other forms of controls available to the ASP.NET programmer.

There are principally three ways of creating web custom controls and we're going look at the implementation options from the point of view of the VS.NET developer. In this first article we'll take a look at composite controls: custom controls composed of standard web server controls. In the second article we shall look at creating custom controls by inheriting from a specific server control and by inheriting from the generic system.web.ui.control class. We'll also consider how to choose which option to take for a given scenario.

First, an introduction to controls.

Controls, controls, controls

Let's start by quickly revisiting the types of controls available within ASP.NET as a backgrounder.

All controls we'll be looking at, you hopefully won't be surprised to know, are server controls ... they run on the server rendering HTML to the client web browser. A sensible differentiating categorisation to make to start with is whether the control is embedded in a web form page (and therefore compiled on demand), or whether it exists in a pre-compiled state.

Microsoft classifies and distinguishes the following types as ASP.NET server controls which exist in the former category:

The first three I shall assume the reader is familiar with. These are the simplest types, as far as the programmer is concerned, and are pre-programmed for us by Microsoft within ASP.NET. User controls are a little different.

A user control is similar to an .aspx page albeit with a different extension (.ascx), inheriting from a different base class and with a different directive. The functionality of a user control can be accessed from an .aspx page via registration and instantiation. User controls are a vast improvement on the only similar option that was available in classic ASP - server-side includes (still available via ASP.NET by the way) and hence a great step forward for the ASP.NET developer, particularly as the languages they are now writing in are fully OO compliant. Here's my definition, borrowing elements from others and adding my own slant:

An ASP.NET user control is a group of one or more server controls (of any or all of the four types discussed) and / or static HTML elements, possibly with additional code, which encapsulate a set of functionality. A user control could simply be an extension of the functionality of an existing server control (such as an image control that can be rotated or a calendar control that stores the date in a text box). Alternatively, it could consist of several elements that work and interact together to delivery a prescribed set of functionality. A key feature is that by exposing properties of the control through the script block of the page (or the code-behind file if using this model), other elements can easily interact with the user control programmatically.

Remember that the four types of control discussed so far are all JIT compiled as part of the featureset offered by ASP.Net, in the context of the .NET Framework, for the web form pages / controls with the extensions .aspx and .ascx. These controls are all derived from the System.Web.UI.Control class hierarchy with its provided properties, methods and events. Our controls don't have to be derived from the control class however – they can be distinct from ASP.NET page framework as pre-compiled components. This however means we lose the support the class provides and we have to get our hands a little dirtier.

Microsoft makes a distinction between web user controls and web custom controls ... which seems a little misleading to me as aren't user controls customisable to an extent as well? Anyway, as already stated two of the main distinctions between a user control and a custom control are that the latter is pre-compiled and more difficult to create than the former. The other main difference is that custom controls are considered more 're-usable' as they can be registered with the global assembly cache (GAC) whereas a copy of each user control is required per application (in the IIS sense). There are also differences with regard to IDE and design time support.

In contrast to a user control, a custom control is compiled into a distinct class. Further, the interface (HTML, JavaScript, etc.) is written out programmatically instead of being part of the user interface portion of the standard page class. This permits the programmer the flexibility to blend the richness of the .NET programming model with as complex an interface as is required. As a custom control is contained in a class, you have access to all the functionality of the .NET Framework: properties can be defined, and functions can be implemented. In fact, the server controls that ship with ASP.NET and Visual Studio.NET are in essence, (complex) custom controls. They are compiled classes that when placed on a page, interact with each other, interact with the page (take advantage of events like OnLoad), emit HTML and script, and provide the power behind the ASP.NET technology.

There are several ways to create custom controls, depending on your requirements:

  1. You can compile a control that combines the functionality of two or more existing controls. For example, if you need a control that encapsulates a button and a text box, you can create it by compiling the existing controls together. Such a control is termed a Composite Control.
  2. If an existing server control almost meets your requirements but lacks some required features, you can customize the control by deriving from it and overriding its properties, methods, and events.
  3. If none of the existing Web server controls (or their combinations) meet your requirements, you can create a custom control by deriving from one of the base control classes. These classes provide all the basic functionality of Web server controls, so you can focus on programming the features you need.

For the remainder of this article I shall review the process of implementing a composite control using Visual Studio .NET. For a non-Visual Studio .NET version you may like to see my article on 15Seconds (see references). In part II of this series of two articles I proceed to examine options 2 and 3 above as well as discussing when you should choose one implementation option over another.

Composite Control Creation

As introduced a composite control is composed of two or more standard web server controls. It is a custom control that inherits from Control or WebControl with a couple of differences from other custom controls:

  1. It overrides the CreateChildrenControls method of the base class. Inside this method it instantiates its constituent controls, adding them to its own controls collection.
  2. It implements the INamingContainer interface which is limited in purpose – it informs that the control has child controls each of which must receive a unique ID.

Conceptually composite controls are similar to user controls in that you build them from simpler controls. However, composite controls have the additional advantages associated with custom controls, namely:

Creating composite controls is generally simpler than creating other custom controls for at least 2 reasons:

  1. You don't need to explicitly render each control as the RenderChildren method of the control takes care of this for you.
  2. You don't need to take any special steps for persisting the state of child controls or implementing additional interfaces.

An issue with child controls is that you must check that they are available before using them – you can't simply assume they are available. Thus you must always invoke the EnsureChildControls method before accessing any child control. This in turn invokes the CreateChildControls method if it has not been invoked already. Alternatively you can check the ChildControlsCreated boolean property.

We shall work through a simple example based on building a composite control from two textbox controls and a button control using VS.NET. The control shall add two numbers. We shall be keeping it simple for the sake of clarity and to demonstrate the key implementation points.

Firstly, create a new project of type web control library in VS.NET, giving the project a suitable name, e.g. Adding.

Next, add a class to the project. Name the class appropriately, e.g. adder.vb. Add the following code.

Listing: adder.vb:

Imports System.Web.UI.WebControls
Imports System.Web.UI
Imports System.Web

Public Class Adder
  Inherits System.Web.UI.WebControls.WebControl
  Implements INamingContainer

  Dim tbFirst As TextBox
  Dim tbSecond As TextBox
  Dim tbResult As TextBox
  Dim WithEvents btnEval As Button

  Sub New()
    MyBase.New()
    Me.Width = Unit.Pixel(300)
  End Sub

  Protected Overrides Sub CreateChildCOntrols()
    tbFirst = New TextBox
    tbSecond = New TextBox
    Dim litAdd As New Literal
    btnEval = New Button
    tbResult = New TextBox

    litAdd.Text = " + "
    btnEval.Text = " = "
    tbResult.ReadOnly = True

    Controls.Add(tbFirst)
    Controls.Add(litAdd)
    Controls.Add(tbSecond)
    Controls.Add(btnEval)
    Controls.Add(tbResult)

  End Sub

  Protected Overrides Sub render(ByVal output As HtmlTextWriter)
    EnsureChildControls()
    RenderChildren(output)
  End Sub

  Private Sub btnEval_click(ByVal sender As Object, ByVal e As EventArgs) Handles btnEval.Click
    EnsureChildControls()
    Try
      Dim result As Double = CDbl(tbFirst.Text) + CDbl(tbSecond.Text)
      tbResult.Text = result.ToString
    Catch ex As Exception
    End Try
  End Sub

  Property result() As Double
    Get
      EnsureChildControls()
      Try
        Return CDbl(tbResult.Text)
      Catch ex As Exception
        Return 0
      End Try
    End Get
    Set(ByVal Value As Double)
      EnsureChildControls()
      tbResult.Text = Value.ToString
    End Set
  End Property

End Class

Points of note:

Build the solution.

Add a new VB.NET web application to your solution.

Add the new component to the VS.NET toolbox: right click the components tab and browse to the dll created for adder.vb.

You'll now be able to drag and drop the new control from the toolbox into your newly created web form and preview the page in your browser. All being well you will be able to enter two numbers and press the '=' button to obtain a result.

Conclusion

I hope the above has served as a useful introduction to controls in general, custom controls and composite controls in particular. The second article in this series of two shall look at two other ways of creating custom controls: by inheriting from a specific server control and by inheriting from the generic system.web.ui.control class. We'll also consider which option you should take for a given scenario.

References

ASP.NET: Tips, Tutorial and Code
Scott Mitchell et al.
Sams

Developing and implementing web applications with VB.Net and VS.Net
Mike Gunderloy
Que

Programming Microsoft Visual Basic.NET
Francesco Balena
Wintellect

Protecting your users from suspect textual data via ASP.NET, a composite control and a little XML.
Chris Sully
15Seconds

You may download the code here.