前言

在上篇写了篇 实战系列之天气预报实时采集 ,有个别同志认为没技术含量,也许正如所说。

只是人各有看法,当我写出一篇文章时,我只是希望:

1:如果你还不懂,请看写法,了解想法

2:如果你已懂,略过写法,请看想法

其实纵观我一直写来的200多篇文章,基本都可以看出那么点痕迹:

一:没有水文

二:没有华丽理论型的文章

三:实战型文章很多

四:文章尽量面向新手的表述,尽量了

今天写篇,还是试图从简入手,希望新手也能有收获,有有没“技术含量”,大伙看着说了~~~要是看不懂,你就点下推荐~

以下为正文

一:Winform下的DataGridView不支持使用DataReader绑定

1:问题产生

在 CYQ.Data 框架 进行到V1.5版本要支持Winform时,曾遇到一个问题,就是无法绑定DataGridView。

2:思考分析试验

MDataTable走的是DataReader方式实现的绑定,除非DataReader无法绑定DataGridView,不然就是自己实现有问题。

因此,做个试验:使用SqlDataReader直接绑定Winform下的DataGridView,发现失败了。

于是大量搜索,发现DataReader实在无法直接绑定DataGridView,通过数据源控件中转绑定的就算了。

3:得出结论

DataReader方式都无法绑定Winform下的DataGridView,我这继承之DataReader的实现方式也就更无从实现绑定了。

只好另寻方法-》DataGridView支持DataTable,于是要从DataTable入手了。

二:DataTable很强大,支持Web又支持Winform

1:分析绑定原理

在以前的MDataTable实现绑定原理篇中,我们研究出要实现绑定,有两种方式:

一种是实现IEnumerable接口,即当初走的DataReader方式实现的绑定。

另一种是实现IListSource接口,即走DataTable方式实现的绑定。

为啥当初不实现DataTable方式的绑定,不就完了,两种都支持~~-_-..现在又得回去折腾IListSource接口的实现

2:深入DataTable绑定原理

我们通过Reflector反编绎看下DataTable继承实现的接口:

public class DataTable : MarshalByValueComponent, IListSource, ISupportInitializeNotification, ISupportInitialize, ISerializable, IXmlSerializable

几乎都是我们平常没用到的接口,不理先,我们关注IListSource怎么实现绑定的。

如果自己看一下IListSource要实现的接口有几个方法:

public interface IListSource
{
    // Methods
    IList GetList();
    // Properties
    bool ContainsListCollection { get; }
}

就两个,太容易了,接着我们要在DataTable 6000多行的代码中找到IListSource的实现,查找是最好的方法:

//DataTable的实现
bool IListSource.ContainsListCollection
{
    get {  return false; }
}

IList IListSource.GetList()
{
    return this.DefaultView;
}

GetList接口没事就返回了个默认视图,又要切进去看视图了。

public DataView DefaultView
{
    get
    {
        DataView defaultView = this.defaultView;
        if (defaultView == null)
        {
            if (this.dataSet != null)
            {
                defaultView = this.dataSet.DefaultViewManager.CreateDataView(this);
            }
            else
            {
                defaultView = new DataView(this, true);
                defaultView.SetIndex2("", DataViewRowState.CurrentRows, null, true);
            }
            defaultView = Interlocked.CompareExchange<DataView>(ref this.defaultView, defaultView, null);
            if (defaultView == null)
            {
                defaultView = this.defaultView;
            }
        }
        return defaultView;
    }
}

切进去就一大堆,实在没心情看下去,省略中间看个头与尾,只知道返回了个DataView。

public class DataView : MarshalByValueComponent, IBindingListView, IBindingList, IList, ICollection, IEnumerable, ITypedList, ISupportInitializeNotification, ISupportInitialize

忽悠:

又是神马般的一堆接口,内部代码太多,实在没心情看;
我只想知道IListSource怎么实现绑定,至于其它有一堆没一堆的我根本不关心,我只要我想要的。
扫了一眼接口,发现是继承了IList,这和IListSource要求的返回值IList是一致的。

神马啊神马,没点头绪,完全找不到绑定的重点,难道说,随便找个IList返回的类就行了?

于是让MDataTable实现IListSource接口,试试看:

public class MDataTable : IDataReader, IEnumerable,System.ComponentModel.IListSource

实现接口:

public IList GetList()
{
    return Rows;
}

接着忽悠:

好说我的Rows也是继承自List<xxx>的,试着绑定~~结果很飘逸,出来完全不是我想象~~
继承折腾DataView,传说DataView也能直接绑定控件的,yo~~有一丝想法

于是看一下其实现IList接口的源码,发现一堆都在操作DataRowView

public class DataRowView : ICustomTypeDescriptor, IEditableObject, IDataErrorInfo, INotifyPropertyChanged

没法忽悠了:

你个XX,从DataTable-》DataView-》DataRowView,再转我头就晕了~~
又是一堆很陌生的接口,于是到这里,我几乎停止了脚步,因为我分析不下去了~~

上WC仔细从头想过:

对于IList<实体>绑定,所有的属性都会被认为是列名,其值为行的值。

而对于DataTable,里面又是怎么认识出列名和分析出值的呢?

1:从DataTable中,我们看到一丝列名提取的相关方法,只是返回->DataRow
2:从DataRow中也看不到提取列名的方法,其关键性的IList接口的相关实现引出了->DataRowView
3:DataRowView?是神秘的所在?一堆继承的接口也是很陌生

回头继续搜索:

转换思路继续大量搜索:换了很多关键字,搜中文又搜E文

结果尽是一堆自定义控件开发的东东,结果印象中在某一篇的googleE文的“网页快照”中发现一段E文,

原文不知是哪了,上次都记得只能打开快照,现在估计能快照都没了,按想象翻译出来的中文大致为:

DataTable能实现其绑定,是因为其实现了ICustomTypeDescriptor,从而获得其属性

偶滴神啊~能从千军万马的E文中,扫到几个关键字不容易啊!!!

如果回过头看上面的DataRowView,就会发现,正好,它实现了接口ICustomTypeDescriptor,
只是遥想当年,我并不像现在写文这么冷静,我当初早把Reflector关掉了,哪还记得DataRowView实现了ICustomTypeDescriptor,
再说ICustomTypeDescriptor对我又是那么的陌生,是那么的陌生,...很陌生。。。

秘密已经出来了

ICustomTypeDescriptor接口,一个移动控件开发人员经常打交道的接口,对于我们却极为陌生的接口

是它,就是它,就是它实现如何识别哪些是列名,哪些是列值。

3:浅入ICustomTypeDescriptor

当初我通过大量的搜索,试图找到相关的应用示例,因为那时我不知道DataRowView,要是知道,我就不用那么辛苦去搜文章了。

如果你搜索此接口,你会发现一堆的文章都是说移动控件开发,我就是从移动控件开发中很辛苦的挖了点示例实现了。

不过此文就不走弯路了,直接分析DataRowView,对于 ICustomTypeDescriptor接口,有很多方法:

public interface ICustomTypeDescriptor
{
    // Methods
    AttributeCollection GetAttributes();
    string GetClassName();
    string GetComponentName();
    TypeConverter GetConverter();
    EventDescriptor GetDefaultEvent();
    PropertyDescriptor GetDefaultProperty();
    object GetEditor(Type editorBaseType);
    EventDescriptorCollection GetEvents();
    EventDescriptorCollection GetEvents(Attribute[] attributes);
    PropertyDescriptorCollection GetProperties();
    PropertyDescriptorCollection GetProperties(Attribute[] attributes);
    object GetPropertyOwner(PropertyDescriptor pd);
}

不过基本是摆设,只因用不到,除了一个接口方法:GetProperties(Attribute[] attributes)

于是我们分析DataRowView对此接口的实现:

PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
{
    if (this.dataView.Table == null)
    {
        return zeroPropertyDescriptorCollection;
    }
    return this.dataView.Table.GetPropertyDescriptorCollection(attributes);
}

继续深入:

internal PropertyDescriptorCollection GetPropertyDescriptorCollection(Attribute[] attributes)
{
    if (this.propertyDescriptorCollectionCache == null)
    {
        int count = this.Columns.Count;
        int num4 = this.ChildRelations.Count;
        PropertyDescriptor[] properties = new PropertyDescriptor[count + num4];
        for (int i = 0; i < count; i++)
        {
            properties[i] = new DataColumnPropertyDescriptor(this.Columns[i]);
        }
        for (int j = 0; j < num4; j++)
        {
            properties[count + j] = new DataRelationPropertyDescriptor(this.ChildRelations[j]);
        }
        this.propertyDescriptorCollectionCache = new PropertyDescriptorCollection(properties);
    }
    return this.propertyDescriptorCollectionCache;
}

关键定位,只是返回一组:DataColumnPropertyDescriptor

那DataColumnPropertyDescriptor是什么?继续深入:

internal DataColumnPropertyDescriptor(DataColumn dataColumn) : base(dataColumn.ColumnName, null)
{
    this.column = dataColumn;
}

两行代码,那个base是啥?是PropertyDescriptor ,实现很简单,把列名传过去就行了,至此,就结束了。

不知道有多少会看到这里,估计本文大伙也就是扫下来,除非某天要应用到,不然只是忽悠下眼球了。

总结下具体实现ICustomTypeDescriptor接口方法:

1:继承实现接口方法
2:重点实现GetProperties(Attribute[] attributes)方法
3:需要自定义属性描述类,而这自定义的属性描述类需要继承自抽象基类PropertyDescriptor
4:GetProperties返回的是自定义属性描述类的集合

三:绑定原理分析完,MDataTable模仿出击

1:MDataTable继承IListSource接口实现

       #region IListSource 成员
        public bool ContainsListCollection
        {
            get
            {
                return true;
            }
        }
        public IList GetList()
        {
            return Rows;
        }
        #endregion

2:MDataRow继承ICustomTypeDescriptor接口实现

A:先实现自定义属性描述类

自定义属性描述类MDataProperty

B:实现重点方法GetProperties(Attribute[] attributes)

        int index = 0;
        PropertyDescriptorCollection properties;
        public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
        {
            if (index == 1)
            {
                return properties;
            }
            index++;
            properties = new PropertyDescriptorCollection(null);

foreach (MDataCell mdc in this)
            {
                properties.Add(new MDataProperty(mdc, null));
            }
            return properties;
        }

OK,此至,MDataTable顺利完成了对Winform下DataGridView的支持。

本文原标题:CYQ.Data 轻量数据层之路 MDataTable绑定Winform之DataGridView 原理高级篇(三十一)

四:总结

微软很强大,MB的Silverlight不支持DataTable的绑定,难道我又要去追随?研究其绑定本质?

不追了,MDataTable增加了ToJson方法和ToList<实体>方法,可直接用json传过去再用反json系列化解析成List<实体>型就可以直接绑定了。

本文有点长,不知有几人,看的明白,看的仔细,估计都是刷的一下从头拉到尾了~~~~

版权声明:本文原创发表于博客园,作者为路过秋天,原文链接:

http://www.cnblogs.com/cyq1162/archive/2010/10/25/1860031.html

DataTable 深入解析数据源绑定原理之高级篇相关推荐

  1. 一起谈.NET技术,DataTable 深入解析数据源绑定原理之高级篇

    前言 在上篇写了篇 实战系列之天气预报实时采集 ,有个别同志认为没技术含量,也许正如所说. 只是人各有看法,当我写出一篇文章时,我只是希望: 1:如果你还不懂,请看写法,了解想法. 2:如果你已懂,略 ...

  2. Sqlserver 高级篇 聚集索引原理

    原理 Sqlserver 高级篇 非聚集索引原理 说完非聚集索引 接着说 聚集索引 聚集索引就是把数据按照 用户设置排好顺序 与非聚集索引不同 非聚集索引不会动数据页 只会新增一个索引表  聚集索引直 ...

  3. SpringMVC源码之参数解析绑定原理

    摘要 本文从源码层面简单讲解SpringMVC的参数绑定原理 SpringMVC参数绑定相关组件的初始化过程 在理解初始化之前,先来认识一个接口 HandlerMethodArgumentResolv ...

  4. GridView绑定数据源 绑定DataReader /DataSet /DataTable

    有一个GridView1 <asp:GridView ID="GridView1" runat="server"></asp:GridView ...

  5. java会员卡的绑定和解绑_SpringMVC源码之参数解析绑定原理

    摘要 本文从源码层面简单讲解SpringMVC的参数绑定原理 SpringMVC参数绑定相关组件的初始化过程 在理解初始化之前,先来认识一个接口 HandlerMethodArgumentResolv ...

  6. this指向-作用域、作用域链-预解析 变量提升-Vue组件传值 父子 子父 非父子-Vue数据双向绑定原理

    目录 this指向 作用域.作用域链 预解析 变量提升 Vue组件传值 父子 子父 非父子 Vue数据双向绑定原理 1.this指向 函数的this指向 看调用.不看声明 (1)普通函数调用 ①函数名 ...

  7. vue模板解析(双大括号的解析)以及双向绑定原理

    1.首先根据正则获取组件中所有的{{}},将{{}}里的值取出在data中取出对应的值,以文本节点的方式放上去. 2.vue有内置的编译器,会将组件转译成AST 3.AST会根据generate得到r ...

  8. 关于DataGridView的数据源绑定字符串两个值得注意的问题

    1. LINQ的查询结果无法直接作为DataGridView的数据源 DataGridView的DataSource属性为object类型,但并不意味着任何类型都可以作为DataGridView的数据 ...

  9. vue的双向绑定原理及实现

    前言 使用vue也好有一段时间了,虽然对其双向绑定原理也有了解个大概,但也没好好探究下其原理实现,所以这次特意花了几晚时间查阅资料和阅读相关源码,自己也实现一个简单版vue的双向绑定版本,先上个成果图 ...

最新文章

  1. ES6变量常量字符串数值
  2. AppBaseJs 类库 网上常用的javascript函数及其他js类库写的
  3. 装饰模式(Decorator Pattern)
  4. 机器学习项目失败的9个原因
  5. 注册博客第一天,有些激动
  6. hadoop学习之一
  7. java继承和多态的实验报告_JAVA,继承和多态实验报告
  8. 学python要考什么证-学python需要考证吗?
  9. 大数据为智慧城市建设添砖加瓦
  10. IMXRT 分散加载文件 修改OCRAM,DTCM、ITCM大小
  11. 【Weiss】【第03章】练习3.20:中缀表达式转后缀表达式
  12. linux中cd命令及范例,15个Linux中的“cd”命令的实际示例
  13. Not So Simple Polygon Embedding CodeForces - 1354C2(计算几何)
  14. 您的DST大礼包请查收
  15. python include的功能_在Python的Config中增加Include功能
  16. android java 图像显示不出来_Java-Android Studio无法在图像视图中显示图像
  17. Ripro子主题Eeesucai-child集成后台美化包源码
  18. python计算器函数图像_Python图形计算器,python,图像,化
  19. 插件搜索我的第一个chrome插件
  20. 企业如何做好网址安全,防止入侵。

热门文章

  1. 为VB应用程序添加英汉翻译功能
  2. 抄底指标:秘密买卖点
  3. SCPPO(三):禅道的使用—项目管理员、开发等人员
  4. 当神经网络遇上量子计算:谷歌证明量子神经网络可训练图像分类
  5. 《Java8实战》-第五章读书笔记(使用流Stream-02)
  6. 一个优雅地探索相关性的新可视化方法
  7. kettle-查询控件
  8. spring cloud 微服务的版本介绍与内部组件详解
  9. 5.3Python数据处理篇之Sympy系列(三)---简化操作
  10. 查询各种物流运输信息