贾超的Blog

<ASP:Blog ID="motto" runat="server" >
  天行健,君子以自强不息
  地势坤,君子以厚德载物
</ASP:Blog >

The new data source controls and the new data binding infrastructure is a cool feature that can simplify development time (especially for simple scenarios and for people without much knowledge of the framework). However, for hardcore developers, not knowing what exactly the new data binding infrastructure does under the hood is problematic and unfortunately, it isn't very well documented anywhere...  I'll try to explain some of the "magic" involved in this. 

BaseDataBound:

All data bound controls designed to use the new data source controls inherit from the BaseDataBound class. This class has the following public properties:

virtual object DataSource  { get; set; }

virtual string DataSourceId { get; set; }


and the following template methods:

   

protected abstract void PerformSelect();

protected abstract void ValidateDataSource(object dataSource);


The first one (DataSource) is what we used to bind data in asp.net 1.x. The second one (DataSourceId) is what lets a data bound control "play" with a data source control.

If you set the DataSource property, the ValidateDataSource method is called, where a control should check that the data source is of a type that it can work with (usually IListSource, IEnumerable or IDataSource). More about the template methods later.

If you change the DataSourceId after the init stage, the DataBind method will be called on PreRender. If you change it after PreRender, it will call DataBind immediately. Note that if you have the DataSourceId set before PreLoad, DataBind is not called by this class!

 The class takes part in the page's life cycle:
* OnInit: if ViewState is disabled, the control will be bound every time on PreRender.
* OnPreLoad: sets an internal flag that marks the end of the init stage.
* OnPreRender: sets an internal flag that marks the begin of the PreRender stage and calls to DataBind.

The class has one public method:

public override void DataBind();


that calls the template method PerformSelect, that should fetch data from the underlying data source.

   

DataBoundControl:

DataBoundControl inherits from BaseDataBound and is the base class for all data bound controls that display tabular or list-style information. This class adds a public property:

public virtual string DataMember { get; set; }

   

that is used to determine the list to use if the data source exposes more than one list of data.

The main task this class accomplishes is to isolate the derived classes from extracting the data from the data source (remember that the control can be bound using the DataSource property or with the DataSourceId property, and it should support both kind of data sources). The data will be presented to the derived classes as an IEnumerable collection in the template method:

protected internal virtual void PerformDataBinding(IEnumerable data);

 

Fortunately the hard work is done by the method ConnectToDataSourceView that gets a reference to a DataSourceView. This is straight forward if the control is bound using DataSourceId, but it has to use a wrapper class in order to expose the DataSource as a data source control (ReadOnlyDataSource that implements IDataSource, returning a view (ReadOnlyDataSourceView) that only supports the select method).

The class takes part in the page's life cycle:
* OnPreLoad: calls the base OnPreLoad and if is the first time the page is requested, or if view state is enabled but the control hasn't been data bound yet, it sets a flag to try to bind data in the OnPreRender stage.
* OnLoad: tries to get a view of the data source (if it doesn't have it yet) and if for some reason the OnPreLoad didn't try to bind the data and we haven't bound the data yet, sets a flag to try to bind data in the OnPreRender stage.

As you can see this class fills the gap that the base class left in order to automatically bind data when the DataSourceId was set before the PreLoad stage.

If the control is bound using DataSourceId, the control captures the DataSourceViewChanged event from the DataSourceView to rebind the control if the data source changes (more on this when explaining the DataSourceView class).

This class implements the template methods defined in BaseDataBound, ValidateDataSource and PerformSelect. The first one checks if the data source implements IListSource, IEnumerable or IDataSource raising an exception in case it doesn't. The second one (PerformSelect) is called by the DataBind method and does the following:
* if we're binding using DataSource, raises the DataBinding event
* gets a DataSourceView from the data source
* marks the control as data bound
* creates the select parameters and calls the DataSourceView's select method, passing a callback that will be called when the select method completes.

The method that will be called when the select method has completed is PerformDataBinding, where the IEnumerable data is passed as the first parameter.

posted on 2007-01-23 17:59  贾超  阅读(336)  评论(0编辑  收藏  举报