In ASP.NET version 2.0, a new data source model enables you to bind data-bound controls to source controls, permitting common data operations — such as paging, sorting, and deleting — to be moved out of the data-bound control itself. This model yields a more flexible data-bound control for page developers and increases the level of reusability.

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.

By deriving from one of the data-bound control base classes, such as the DataBoundControl class or the CompositeDataBoundControl class, your custom data-bound control automatically inherits many built-in features, including the following:

Data source support for the IDataSource interface and its related DataSourceView class, which provides named views of data, the ability to query the types of operations supported by the data store, and on-demand data loading functionality.

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.

Support for automatic data binding that invokes data-binding logic as late as possible during the page life cycle and 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.

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 your control is used at design time on a visual design surface, such as Design view in Visual Studio.

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.

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

Step

Step Summary

Choose a data-bound control base class.

Extend an existing data-bound control class that already provides many of the features you need, or derive from one of the base data-bound control classes.

Expose data-binding properties.

Configure your custom control to expose data-binding properties that are in addition to the minimum required data-binding properties exposed by base data-bound control classes.

Initiate data retrieval.

Retrieve the data that the page developer assigned to your control by doing the following:

Override the PerformSelect method of the base data-bound control class.

Call the GetData method of the base data-bound control class to retrieve the control's data-source view

Call the Select method of the DataSourceView object to initiate data retrieval and specify the callback method that will receive the data.

Handle the retrieved data.

Provide the callback method that you specified as a parameter in the Select method. The callback method must have a single parameter of type IEnumerable to receive the data. If any processing of the data is required by your control, it should occur within this callback method.

Create the UI objects representing the data

Provide an override of the PerformDataBinding method. You must execute the following tasks within this method:

Call the PerformDataBinding method to allow any other code relying on this method to execute.

Enumerate through the data collection and create any child controls that will represent the data in the UI display.

Choose a Data-Bound Control Base Class

Control developers can extend one of the available data-bound control base classes to create a custom data-bound control. The following table provides a list of data-bound base classes that are available in ASP.NET 2.0. Review the descriptions of each class and then determine which base class best fits the requirements of your custom data-bound control. For more detailed information about each base class for data-bound controls and implementation examples, see the reference documentation for each class. For more information about data-bound controls provided by ASP.NET, see ASP.NET Data-Bound Web Server Controls Overview.

This is the base class for controls that display their data in hierarchical form. It serves as the basis for data-bound tree-based controls, such as TreeView and Menu.

Provided Data-Binding Properties

The base data-bound control classes already provide the exposed data-binding properties needed to enable a page developer to bind a data source to a control. No additional work is needed on the part of the control author. By deriving from DataBoundControl, for example, a custom control inherits three exposed data-binding properties: DataSourceID, DataSource, and DataMember. A page developer can then specify the source of the data to which the control will bind by setting the value of either the DataSource or the DataSourceID properties.

The DataSourceID property enables the page developer to specify the ID of a control that represents the data source from which the data-bound control retrieves its data.

The DataSource property enables the page developer to bind a data-bound control directly to data-objects of these two types:

Additional data-binding properties, such as the DataMember property, allow the page developer to specify the portion of the data collection to which the control should bind.

For more information about the exposed data-binding properties provided by each data-bound control class or data-bound base class, see the reference documentation for each class.

Exposing Custom Data-Binding properties

When exposing your own custom data-binding properties in a custom control or overriding existing data-binding properties, you should call the OnDataPropertyChanged method if the control has already been initialized. This forces the data-bound control to rebind the data so it can use the new data-binding property setting.

The following code example shows a property that belongs to a derived data-bound control class. The example demonstrates how a data-bound control can call the OnDataPropertyChanged method if a property that identifies a data source is changed after the data-bound control is initialized.

Initiate Data Retrieval

Data retrieval is initiated within an override of the PerformSelect method inherited by your control's base data-bound control. Within this override you call to retrieve the data and specify a callback method that will handle the data once it is returned.

To retrieve data, complete the following tasks in the overridden PerformSelect method:

Call the Select method of the retrieved DataSourceView to initiate data retrieval and specify the callback method that will handle the retrieved data. The Select method operates asynchronously, so other processing is allowed while the data is being retrieved.

Handle the Retrieved Data

Create your own callback method to accept the retrieved data. This is the callback method you specified when the Select method was called within the override of the PerformSelect method. The callback method is required to contain only a single parameter of the type IEnumerable. In your callback method you can do any processing of the returned data, if required by your control. As a last step, call the PerformDataBinding method.

privatevoid OnDataSourceViewSelectCallback(IEnumerable retrievedData)
{
// Call OnDataBinding only if it has not already been // called in the PerformSelect method.if (IsBoundUsingDataSourceID)
{
OnDataBinding(EventArgs.Empty);
}
// The PerformDataBinding method binds the data in the // retrievedData collection to elements of the data-bound control.
PerformDataBinding(retrievedData);
}

Create the UI Objects Representing the Data

Within an override of the PerformDataBinding method, you create the child controls that will represent the data. The data collection is enumerated, and the child controls are created and their properties set based on each data item. By adding the new child controls to the control's Controls collection, the child controls will be rendered for you. The control hierarchy renders during the control's inherited Render method. You might choose to override the Render method to do special rendering required by your custom control, such as including additional HTML elements or special rendering for display during design mode.

To create the UI objects representing the data, override the PerformDataBinding method and complete the following tasks:

Call the PerformDataBinding method to allow any other code relying on this method to execute.

Enumerate through the data collection and create any child controls that will represent the data in the UI display. Add each child control to the control's collection by calling the control's Add method.

The following code example illustrates overriding the PerformDataBinding method. The PerformDataBinding method is called to allow any other code relying on this method to execute. The data collection is enumerated and child controls are created to represent the data in the UI display.