Developing Custom Data-Bound Web Server Controls for ASP.NET 1.1

An ASP.NET data-bound Web server control provides a user interface (UI) for a data source representing a collection of records or items. The GridView Web Server Control Overview, DataList Web Server Control Overview, and Repeater Web Server Control Overview server controls are examples of data-bound Web server controls. For more information about data-bound controls provided with ASP.NET, see ASP.NET Data-Bound Web Server Controls Overview.

This topic introduces the steps required to implement a minimum version of a custom ASP.NET version 1.1 compatible data-bound server control. For more information about creating custom data-bound controls in ASP.NET version 2.0 see, Developing Custom Data-Bound Web Server Controls for ASP.NET 2.0. For more information about the general architecture and implementations of custom controls, see Developing Custom ASP.NET Server Controls and Walkthrough: Developing and Using a Custom Web Server Control.

When to Create a Custom Data-bound Control

Before creating your own custom data-bound control, review the capabilities of the data-bound controls already provided with ASP.NET. Existing controls might meet your needs, or you might decide to create a custom control that extends an existing control which already provides many of the features you need. For more information about data-bound controls provided with ASP.NET see, ASP.NET Data-Bound Web Server Controls Overview.

Here are some reasons you might decide to create a custom data-bound control:

  • Your particular needs require custom UI, custom data-sorting features, or custom data-editing features that are not available in existing data-bound controls.

  • You want to create a custom data bound control that that is pre-compiled and redistributable.

  • You want to extend the features of a data-bound control that is already provided with ASP.NET.

  • You want to create a data-bound control with a custom designer that fits your specific needs.

Basic Functionality of a Custom Data-Bound Control

By deriving from the Control or WebControl class, your custom data-bound control automatically inherits many built-in features, including the following:

  • An explicit data-binding model that supports data-binding expressions. The ASP.NET explicit data-binding model performs data binding only when needed, rather than on each postback. After a page performs the first data-binding request, subsequent requests attempt to retrieve the data from view state. This enhances performance by avoiding the need to reconnect to the data source on every request.

  • Support for data-binding expressions, which enables page developers to create bindings between an exposed, specially marked property of your control and a data source. For more information about data-binding expressions, see Data-Binding Expressions Overview

Utilizing Available Design Time Features

There are design-time features available to all Web server controls that you might want to consider for your custom data-bound control. You can create a designer class and control templates for your custom control. These features are invoked when you work with your control on a visual design surface, such as Design view in Visual Studio.

Creating a control designer can greatly increase your custom control’s usability at design time by providing a design-time interface that enables page developers to customize control properties. For an overview of ASP.NET control designers, see ASP.NET Control Designers Overview. For examples, see HierarchicalDataBoundControlDesigner and Walkthrough: Creating a Basic Control Designer for a Web Server Control.

By creating a templated control, you provide page developers the flexibility to specify the controls and markup that define control's user interface. For an example of a custom templated control, see Templated Server Control Example.

Implementing a Custom Data-bound Control in ASP.NET

The following table summarizes the requirements that are specific to implementing a data-bound server control in ASP.NET 1.1. After the table, you will find more detailed information about each of the implementation requirements.

Requirement

Description

Expose a DataSource property.

Enables a page developer using your control to specify the data source to bind to.

Override the DataBind method and create logic to enumerate the object in the associated data source.

In this method’s logic:

  • The OnDataBinding method of the server control is invoked to raise the DataBind event. This allows any data-binding expressions the page developer may have associated with your data-bound server control to be evaluated.

  • You must provide all logic to enumerate the objects in the data source here.

  • All child controls are created to visually represent the data source.

Create a child control hierarchy by overriding the CreateChildControls method

On postback, recreates child controls and binds them to data stored in view state during a preceding DataBind call.

Note

Consider creating a single helper method to be invoked by the DataBind and the CreateChildControls methods to create the child control hierarchy. For example, the helper method that creates the child control hierarchy could accept a Boolean value, which indicates that the data is from the bound source or the view state. This pattern keeps the creation of the control’s child control hierarchy on one common code path. For an example of this pattern, see Walkthrough: Creating a Custom Data-Bound ASP.NET Web Control for ASP.NET 1.1.

Exposing a DataSource property

An ASP.NET 1.1 data-bound control derived from Control or WebControl must expose a DataSource property to enable the page developer to select the data collection that your server control will bind to. At run time, your custom data-bound control enumerates through the data collection assigned to the DataSource property as it creates and binds UI elements to represent that data.

A data-bound server control can bind to these types:

The following code example shows how to expose a DataSource property for a data-bound control. The DataSource type is declared as type IEnumerable.

<Category("Data"), DefaultValue(""), Description("An exposed data source: A public member of type IEnumerable to bind to such as an Array, ArrayList or Hashtable.")> _
Public Overridable Property DataSource() As IEnumerable
    Get
        Return _dataSource
    End Get
    Set(ByVal value As IEnumerable)
        If TypeOf value Is IEnumerable OrElse value Is Nothing Then
            _dataSource = value
        Else
            Throw New ArgumentException()
        End If
    End Set
End Property
[
Category("Data"),
DefaultValue(""),
Description("An exposed data source: A public member of type IEnumerable to bind to such as an Array, ArrayList or Hashtable.")
]
public virtual IEnumerable DataSource
{
    get
    {
        return _dataSource;
    }
    set
    {
        if ((value is IEnumerable) || (value == null))
        {
            _dataSource = value;
        }
        else
        {
            throw new ArgumentException();
        }
    }
}

This example begins with metadata attributes, such as [Category], [DefaultValue] and [Description], that provide information used by design tools, the ASP.NET page parser, the ASP.NET run time, and the common language runtime (CLR). The BindableAttribute notifies a visual designer that the property browser can display the control's bindable properties in a dialog box. (For example, in Visual Studio, bindable properties are displayed in the DataBindings dialog box.) The CategoryAttribute specifies how to categorize the property in a visual designer's property browser. For more information about the metadata attributes, including the ones used in this example, see Metadata Attributes for Custom Server Controls.

The set accessor for the DataSource property verifies the value to set is either null or of type IEnumerable. Therefore, in this example the page developer can bind data to any IEnumerable type, such as an Array, ArrayList, or Hashtable. Alternatively, the developer can set the DataSource to null until a suitable data source of type IEnumerable is available.

Note

If you want your custom data-bound server control to be able to bind to either an IEnumerable or IListSource data type, you can declare your DataSource property as the generic type Object. In that case, the set accessor that exposes your DataSource property must verify the type of the object passed to it, and then implement either IEnumerable or IListSource.

Overriding the DataBind Method and Enumerating the Associated Data Source

You provide an override to the base DataBind method in your custom control to enable two tasks to be preformed: enumerate through the bound data collection, and create the child-control hierarchy that will represent that data. The following list summarizes tasks you must perform within the overridden DataBind method:

  • Invoke the base OnDataBinding method of your custom control.

  • Clear any existing child controls.

  • Clear all child-control view state.

  • Track state so that changes during data binding are persisted in view state.

  • Create the child-control hierarchy.

  • Set the ChildControlsCreated property to true.

Begin with invoking your control's base OnDataBinding method from within the overridden DataBind method in your control. Invoking your control’s base OnDataBinding method causes all data-binding expressions for the control to be evaluated. The following code example shows how to invoke the OnDataBinding method in a data-bound server control as the first task within its overridden DataBind method.

public override void DataBind()
{
    base.OnDataBinding(EventArgs.Empty);
}
Public Overrides Sub DataBind()
    MyBase.OnDataBinding(EventArgs.Empty)
End Sub

Next, clear the existing child controls. Since the child-control hierarchy must be recreated with each postback based on the data about to be bound, any existing child controls must be cleared by invoking the control's inherited Clear method, as shown in the following code example.

public override void DataBind()
{
    base.OnDataBinding(EventArgs.Empty);
    Controls.Clear();
}
Public Overrides Sub DataBind()
    MyBase.OnDataBinding(EventArgs.Empty)
    Controls.Clear()
End Sub

New child controls will be created to represent newly bound data, so any view state for existing child controls must be discarded. You clear view states of all the child controls by invoking the control's inherited ClearChildViewState method.

After you have cleared view state for any existing child controls, start the control's view-state tracking by calling the control's inherited TrackViewState, which takes care of tracking view state for you. The control's state tracking is started before creating the child control hierarchy so that any changes in the child control hierarchy made during data binding are persisted in view state. Since a page developer can invoke DataBind during the page's PreInit event you cannot rely on your control's base class to track view state that occurs after that stage in the page life cycle. In this case the view-state tracking for the control would occur too late in the process.

The following code example illustrates a data-bound server control invoking its TrackViewState method.

public override void DataBind() 
{
    TrackViewState();
}
Public Overrides Sub DataBind()
    TrackViewState()
End Sub

Next, create the child-control hierarchy. The child-control hierarchy visually represents the data source that your custom data-bound control is bound to and is created when either the overridden DataBind or CreateChildControls methods of your custom control are invoked by your control's base class. When your control's overridden DataBind is invoked by the control's base class, your control's child hierarchy is created based on the bound data source. When your control's overridden CreateChildControls method is invoked by the base class, the child control hierarchy is created based on the data saved in view state.

The creation of the child control-hierarchy is triggered by the invoking of the control’s DataBind method. The control enumerates through the data provided by the exposed DataSource property and instantiates a new child control to represent each data item. For example, if the data source is an array of strings to be bound to the Text property of Button controls, iterate through the array, creating a new Button control with its Text property assigned to the iterated data item represented as a string.

After creating the child-control hierarchy, set the ChildControlsCreated property to true to indicate that the CreateChildControls method should not be invoked by the base class.

The following code example illustrates a data-bound server control setting its ChildControlsCreated property to true.

public override void DataBind()
{
     ChildControlsCreated = true;
} 
Public Overrides Sub DataBind()
    ChildControlsCreated = True
End Sub

Your custom data-bound control class must provide an overridden CreateChildControls method in which the control re-creates its child control hierarchy and allows saved view state to be applied. (Saved view state is tracked during the most recent call to the control’s DataBind method.)

The following list summarizes the tasks you must perform in the overridden CreateChildControls method:

  • Clear any existing child controls.

  • Create the child-control hierarchy if view state is available.

Before you re-create the child-control hierarchy, you must clear any existing child-control objects. This is done by invoking the control's Clear method.

The following code example illustrates a data-bound server control invoking its Clear method.

public override void CreateChildControls()
{
    Controls.Clear();
}

As the last step, you create the child-control hierarchy. The CreateChildControls method must re-create the child-control hierarchy if there is view state available. As long as the same number and types of child controls are created in the same hierarchy, the saved view state is automatically applied to the child controls. Your control can save the information that it needs to re-create the same number, type, and hierarchy of child controls in your control's ViewState property. For more information about saving control view state, see ViewState. For a complete code example demonstrating the creation of child-control hierarchy in a custom data-bound control, see Walkthrough: Creating a Custom Data-Bound ASP.NET Web Control for ASP.NET 1.1.

Building Your Custom Server Control

For information about building your custom data-bound Web server control and using it in a Web page, see Building the Custom Server Control Examples.

Note

You must add a reference to the System.Design assembly in order to include it in your compilation.

See Also

Tasks

Walkthrough: Creating a Custom Data-Bound ASP.NET Web Control for ASP.NET 1.1

Walkthrough: Developing and Using a Custom Web Server Control

Concepts

ASP.NET Data-Bound Web Server Controls Overview

Metadata Attributes for Custom Server Controls

ASP.NET Control Designers Overview

Reference

HierarchicalDataBoundControlDesigner

Other Resources

Developing Custom ASP.NET Server Controls