在读Clinglingboy的asp.net控件开发基础(18)时,Clinglingboy对其进行了重点讲解。可是我感觉在如何将具有IListSource接口的数据源最终转化为DataView说的还不是十分清楚,下面我这一部分再详细的说一下。
首先还是贴一下关键的DataSourceHelper类

    }


(1)如果传入的数据源类型是IEnumerable的话,可以直接返回

关于模板控件如何实现多数据源绑定的问题            if (dataSource is IEnumerable)
            }

 这里像Array、ArrayList、SqlDataReader、DataView等都直接或者间接的实现了IEnumerable接口。

(2)如果传入的类型非IEnumerable,那么代码会判断数据源是否实现了IListSource接口,因为如果实现了IListSource接口,那么我们同样可以利用此接口的GetList方法返回一个IList,而IList继承IEnumerable,同样可以进行数据绑定。当然如果数据源没有实现IEnumerable和IListSource,数据源就不可绑定。
这里像DataTable、DataSet都实现了IListSource接口。
DataTable实现的GetList方法

关于模板控件如何实现多数据源绑定的问题 IList IListSource.GetList()
 }

返回了一个DataView
DataSet实现的GetList方法

关于模板控件如何实现多数据源绑定的问题 IList IListSource.GetList()
 }

 

返回了一个DataViewManager。

通过判断IListSource中的ContainsListCollection,我们可以知道包含多个DataTable的DataSet还是只有一个DataTable,对于后者,由于已经通过GetList方法得到了它的DataView,而DataView又实现了IEnumerable接口,问题也解决了。

问题现在集中到如何处理DataSet的数据源,我们来看一下DataViewManager类,除了几个public的属性,还有一个DataViewManagerListItemTypeDescriptor类型的Item值得我们注意,后面会讲解此类。同时DataViewManager类实现了ITypedList接口,接下来利用ITypedList.GetItemProperties(object)得到PropertyDescriptorCollection.


关于模板控件如何实现多数据源绑定的问题

我们看一下ITypedList.GetItemProperties(object)的代码,其中关键一句

return ((ICustomTypeDescriptor) new DataViewManagerListItemTypeDescriptor(this)).GetProperties();

看来DataViewManagerListItemTypeDescriptor的GetProperties方法可以得到PropertyDescriptorCollection。此类是Framework的一个内部类,实现了ICustomTypeDescriptor接口。

那么ICustomTypeDescriptor是做什么用的呢。我们来看一下msdn:

ICustomTypeDescriptor 使对象得以提供有关自身的类型信息。通常,当对象需要动态类型信息时使用此接口。相反,TypeDescriptor 提供从元数据获得的静态类型信息。

大家可能对这句话不太明白,我解释一下,这里我用PropertyGrid举例,不熟悉的可以在网上查,实际上我感觉PropertyGrid在和某个类绑定的时候,默认的是用TypeDescriptor 提供从元数据获得的静态类型信息。如下图

 关于模板控件如何实现多数据源绑定的问题
但是有些情况,你需要用到 PropertyGrid 去绑定一个属性/值的集合,但是这个属性/值的集合并不适合写成一个固定的类。

比如你想用 PropertyGrid 绑定XML 里的数据。或者数据库的某个表。

假设你有 1000 个XML 文件,每个 XML 所取到的属性集合各不一样,你不可能为每个XML 文件都写一个类 。

或者你的某个数据表有1000 条记录,该表有 a 字段的值表示属性名称, b字段的值表示属性值,你不可能写一个类,定义1000个属性。

这时候,我们就希望是否能够将一个动态的属性/值的集合与Property 绑定。通过实现ICustomTypeDescriptor,我们就可以完成动态的属性/值的集合与Property 绑定。这里参考了PropertyGrid 绑定动态的属性与值的集合文章,这篇文章对大家理解ICustomTypeDescriptor会有很大的帮助,文章的代码是VB2005,我用c#2003重新写了一下,这两段代码我会在文章后面给出下载,建议大家先读这篇文章以帮助理解。我把这篇文章的几个类的关键部分列出来。

    }

 

    }

 

    }

回到问题上来,在我们实现了ICustomTypeDescriptor,不需要和PropertyGrid绑定,我们可以得到一个PropertyDescriptorCollection。那么就来具体看看对比。

其中上文的XProp -->  DataTable

                 XProps 的GetProperties方法--> ((ITypedList) DataViewManager).GetItemProperties方法

                 XPropDescriptor--> DataTablePropertyDescriptor

大家会看到((ITypedList) DataViewManager).GetItemProperties方法返回了DataTablePropertyDescriptor的PropertyDescriptorCollection集合;XProps的GetProperties方法返回了XPropDescriptor的PropertyDescriptorCollection集合

在DataTablePropertyDescriptor会有一个DataTable的属性,并且该类复写了GetValue方法,取得值,这个和XPropDescriptor中有XProp属性,且复写了GetValue方法是一致的。唯一不同的是XPropDescriptor的GetValue方法只是将具体的XProp的Value返回,而DataTablePropertyDescriptor中的GetValue方法又利用DataTable进一步操作返回了DataView。

我们现在知道ITypedList.GetItemProperties(object)是怎么得到PropertyDescriptorCollection(确切的说是DataTablePropertyDescriptor),我们接着利用propDesc = propDescCol.Find(dataMember, true)去在集合中查找名字为dataMember值也就是具体的表名,以返回待操作的DataTablePropertyDescriptor。在((ICustomTypeDescriptor) new DataViewManagerListItemTypeDescriptor(this)).GetProperties()方法建立集合的时候采用了表名作为名值对的名,大家可以对照代码看看。接下来再看这段代码

关于模板控件如何实现多数据源绑定的问题object listitem = list[0]; 
关于模板控件如何实现多数据源绑定的问题
//获取组件属性当前值
关于模板控件如何实现多数据源绑定的问题
object member = propDesc.GetValue(listitem);

list是什么?实际上是我们在前面得到的DataViewManager.IListSource listSource = (IListSource)dataSource;
list = listSource.GetList();

由于DataViewManager实现了IList接口,因此我们可以用list[index]的形式取得具体的元素,这里我们看到是取得了item的值,还记得我们前面让大家留意DataViewManager的Item属性,实际上它就是一个DataViewManagerListItemTypeDescriptor。propDesc是一个DataTablePropertyDescriptor,来看一下他的GetValue(object)代码

 

关于模板控件如何实现多数据源绑定的问题public override object GetValue(object component)
 

而DataViewManagerListItemTypeDescriptor的GetDataView的代码 

关于模板控件如何实现多数据源绑定的问题internal DataView GetDataView(DataTable table)
 

实际上这一步就是利用DataTable构建DataView,我觉得也可以用其他的方法完成,给DataViewManagerListItemTypeDescriptor增加一个内部的GetDataView方法反而弱化了TypeDescriptor的功能。

到这里,我们就可以返回一个(IEnumberable)DataView了。

PropertyGrid 绑定动态的属性与值的集合文章代码下载:

 

ICustomTypeDescriptorTestVB.zip(VB2005)

ICustomTypeDescriptorTestCSharp.zip(C#2003,其中VB2005使用了范型,改写的时候用了CollectionBase,效果一样)


 

 

 

 

 

 

相关文章:

  • 2022-01-25
  • 2022-12-23
  • 2022-12-23
  • 2021-09-29
  • 2021-07-28
  • 2021-10-12
  • 2022-12-23
  • 2022-01-21
猜你喜欢
  • 2022-12-23
  • 2021-06-18
  • 2021-08-30
  • 2021-08-02
  • 2021-11-10
  • 2021-11-13
  • 2021-10-20
相关资源
相似解决方案