Inside ASP.NET 2.0 DataBound Control - 3
本文旨在阐述ASP.NET 2.0新的数据绑定控件架构,并且逐一介绍每一个控件。
HierarchicalDataBoundControl
HierarchicalDataBoundControl是一个抽象类,从BaseDataBound类派生,用来绑定树状数据。所有用来显示或编辑树状数据的绑定控件都应该从该类派生,例如TreeView以及Menu控件。
HierarchicalDataBoundControl实现的主要功能是从HierarchicalDataSourceControl中获取数据,派生类将不再需要关心如何从数据源中获取数据,而只需要关心其本身的业务逻辑即如何展示绑定数据。
1. HierarchicalDataBoundControl 接口
2{
3 protected virtual HierarchicalDataSourceView GetData(string viewPath);
4 protected virtual IHierarchicalDataSource GetDataSource();
5
6 protected override void PerformSelect();
7 protected internal virtual void PerformDataBinding();
8
9 protected override void ValidateDataSource(object dataSource);
10}
ValidateDataSource
当用户设者HierarchicalDataBoundControl的DataSource属性时,控件会调用ValidateDataSource方法来验证绑定数据源是否为合法的数据源,通过该方法的实现我们可以知道绑定数据源必须是IHierarchicalEnumerble或者IHirarhiclDataSource对象。
2{
3 if (((dataSource != null) && !(dataSource is IHierarchicalEnumerable)) && !(dataSource is IHierarchicalDataSource))
4 {
5 throw new InvalidOperationException());
6 }
7}
另外如果用户通过DataSourceID属性来设置数据源,当进行数据绑定时控件会尝试向数据源检索HierarchicalDataSourceView,如果检索不到,将抛出同样的异常。
GetDataSource
该方法将会从绑定数据源中检索相关联的IHierarchicalDataSource对象,而绑定数据源是用户通过DataSourceID属性指定的,也就是说GetDataSource方法只负责从DataSourceID属性指定的数据源中检索IHierarchicalDataSource对象。
而控件的另外一个私有方法ConnectToHierarchicalDataSource则会调用GetDataSource方法,无论控件通过何种方式进行数据绑定,该方法都会返回与数据源关联的IHierarchicalDataSource对象。
我们再来看一下IHierarchicalDataSource这样一个接口:
2{
3 event EventHandler DataSourceChanged;
4
5 HierarchicalDataSourceView GetHierarchicalView(string viewPath);
6}
该接口将会返回一个HierarchicalDataSourceView对象,通过该对象我们就可以检索其背后的树状数据了。
GetData
从数据源中获取HierarchicalDataSourceView 对象,另用该对象数据绑定控件可以来操作数据。HierarchicalDataSourceView类定义了Select操作,通过Select方法可以进行数据检索。
ASP.NET 2.0通过IHierarchicalEnumerable和IHierarchyData两个接口来组织树状的数据结构,通过这两个接口我们可以检索到树状数据的每一个节点。
2{
3 IHierarchyData GetHierarchyData(object enumeratedItem);
4}
5public interface IHierarchyData
6{
7 IHierarchicalEnumerable GetChildren();
8 IHierarchyData GetParent();
9
10 bool HasChildren { get; }
11 object Item { get; }
12 string Path { get; }
13 string Type { get; }
14}
IHierarchicalEnumerable接口负责在兄弟节点之间进行枚举迭代,而IHierarchyData接口则负责在父子节点之间进行枚举迭代。
PerformSelect和PerformanDataBinding
HierarchicalDataBoundControl重载了PerformSelect方法,该方法只是设定数据绑定内部标志以及触发绑定事件,而将数据绑定的操作委托给了新定义的虚方法PerformDataBinding。
从该类派生的子类只需要重载PerformDataBinding方法来进行数据展示及其本身业务逻辑的处理就可以了。具体实现应该是在PerformDataBinding方法中通过GetData方法获取HierarchicalDataSourceView对象,然后进行数据检索。
2. 页面生命周期
HierarchicalDataBoundControl在页面生命周期中定义了一些时机来进行数据绑定的处理:
OnPagePreLoad
如果是页面进行第一次请求的话,则控件要求进行数据绑定。另外如果是一次PostBack的话,并且控件仍然没有进行数据绑定,同时Enable ViewState,控件也会要求数据绑定。
2{
3 base.OnPagePreLoad(sender, e);
4 if (this.Page != null)
5 {
6 if (!this.Page.IsPostBack)
7 {
8 base.RequiresDataBinding = true;
9 }
10 else if (base.IsViewStateEnabled && (this.ViewState["_!DataBound"] == null))
11 {
12 base.RequiresDataBinding = true;
13 }
14 }
15 this._pagePreLoadFired = true;
16}
这一点跟DataBoundControlde处理是一样的。
OnLoad
在OnLoad的时候控件会向绑定数据源检索IHierarchicalDataSource对象,并且进行备份。然后如果发现控件没有进行数据绑定的话,判断页面是否为第一次请求,如果是则要求进行绑定,如果不是当控件Enable ViewState,也会要求数据绑定。
2{
3 base.ConfirmInitState();
4 this.ConnectToHierarchicalDataSource();
5 if (((this.Page != null) && !this._pagePreLoadFired) && (this.ViewState["_!DataBound"] == null))
6 {
7 if (!this.Page.IsPostBack)
8 {
9 base.RequiresDataBinding = true;
10 }
11 else if (base.IsViewStateEnabled)
12 {
13 base.RequiresDataBinding = true;
14 }
15 }
16 base.OnLoad(e);
17}
3. 小结
HierarchicalDataBoundControl定义了树状数据绑定控件的基类,其主要功能是实现了向层级的数据源检索数据,其派生类只需要针对获得的树状数据包进行自己的业务处理就可以了。
4. 结束语
这是Inside ASP.NET DataBoundControl系列文章中的第三篇,第一篇介绍了BaseDataBoundControl,后两篇分别介绍了DataBoundControl和HierarchicalDataBoundControl,前者用于绑定表状数据,后者用于绑定树状数据。
以后如果有时间的话,我会写一下DataSourceControl以及DataSourceView,这两块其实是跟DataBoundControl密不可分的。
有什么问题大家可以互相交流,取长补短,共同进步。