我们开端探寻绑定之法,领悟想法

前言

继上1节过后,大家开始搜索绑定之法

 

第二一遍想,我们日常是拿什么绑定到数码控件的:List<实体类>,DataTable,DataSet,DataView之类的,

在上篇写了篇
实战连串之天气预告实时采集
,有各自同志觉得没技术含量,恐怕正如所说。

而写法也就像此个样:

只是人各有眼光,当自身写出1篇文章时,小编只是梦想:

xxxx.DataSource=List<实体类>….等

1:假如您还不懂,请看写法,驾驭想法

XXxx.DataBind();

二:假如你已懂,略过写法,请看想尽

于是乎,大家就从那几个事物动手了,要不然也措不着头脑该往何地找

 

DataSource这东西要给赋值,那我们开辟reflector.exe看看那几个中究竟有点什么事物先

实质上纵观笔者一贯写来的200多篇小说,基本都足以见到那么点划痕:

按下F三,搜索Repeater,当然也能够搜别的象GridView之类的别的控件,反正搜有DataSource那东西的就行了

1:未有水文

OK,定位Repeater之后,展开DataSource属性,看源码如下:

2:未有华侈理论型的稿子

图片 1图片 2DataSource
[Bindable(true), WebSysDescription(“BaseDataBoundControl_DataSource”), WebCategory(“Data”), DefaultValue((string) null), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public virtual object DataSource
{
    get
    {
        return this.dataSource;
    }
    set
    {
        if (((value != null) && !(value is IListSource)) && !(value is IEnumerable))
        {
            throw new ArgumentException(SR.GetString(“Invalid_DataSource_Type”, new object[] { this.ID }));
        }
        this.dataSource = value;
        this.OnDataPropertyChanged();
    }
}

3:实战型小说很多

 

四:小说尽量面向新手的发布,尽量了

哟,yoyo~~value is IListSource 大概value is
IEnumerable,要是否那三种档次,还抛万分

 

突然记起来,之前也抛过尤其的,还是粤语的,突然想看看那个11分的汉语版是啥样的

后天写篇,依旧试图从简动手,希望新手也能有获得,有有没“技术含量”,大伙望着说了~~~倘若看不懂,你就点下推荐图片 3~

于是,随便找了二个页面,拉了贰个GridView进去,后台写上这么几行代码:

 

object value=”hello”;
GridView1.DataSource = value;
GridView1.DataBind();

以下为正文

来呢,给自家痛快的报错吧,运维。。。。。

 

刷。。出来了那样点东西:

一:Winform下的DataGridView不辅助接纳DataReader绑定

Item
h
e
l
l
o

壹:难题产生

日光,这么牛B,还给拆成字符给自家列表下来了,从reflector.exe搜索object,发现没继续自IListSource
或IEnumerable。

在 CYQ.Data
框架
 实行到V一.五版本要援救Winform时,曾遇到一个题材,正是力不从心绑定DataGridView。

日光,把object value=”hello”,改成object
value=壹,一试,运转,刷,期待的国语褐色十分竟然终于来了

 

“数据源的项目无效。它必须是 IListSource、IEnumerable 或 IDataSource。”

贰:思量分析试验

不截图了,麻烦。直接加玛瑙红好了。突然脑子壹闪,从reflector.exe搜索String,

MDataTable走的是Data里德r格局落成的绑定,除非DataReader不能绑定DataGridView,不然正是上下一心达成极度。

发现依旧String还真的继承了IEnumerable那东西。唉。。。

之所以,做个考试:使用SqlDataReader直接绑定Winform下的DataGridView,发现战败了。

于上难题起始紧锣密鼓了,核心就在IListSourceIEnumerable上了,只要让大家的自定义MDataTable完结在那之中之1的接口,就顺手了。

于是大方追寻,发现DataReader实在十分的小概直接绑定DataGridView,通过数据源控件中间转播绑定的纵然了。

先用reflector.exe看一下IListSource这东西:

 

public interface IListSource
{
    // Methods
    IList GetList();

3:得出结论

    // Properties
    bool ContainsListCollection { get; }
}

Data里德r格局都爱莫能助绑定Winform下的DataGridView,笔者那前仆后继之DataReader的落真实意况势也就更未能达成绑定了。

嗯,原来那接口就是回到二个IList,那大家的自定义的MDataTable好像也有List接口了,怪不得直接绑定,

只能另寻方法-》DataGridView帮衬DataTable,于是要从DataTable出手了。

却绑定了一个些类的实业性质,看来估算有一点都不小大概和这几个List<实体类>一类的就绑定都差不离了.

 

既是大家是简化的模仿DataTable,那就从DataTable找起好了,照旧用reflector,exe搜索DataTable并一定,

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

惊人发现,DataTable竟然持续了IListSource接口,那它不是和自家的二个样,咋它就能绑定就见惯司空,笔者的就不可能。

 

阳光贰个。。

一:分析绑定原理

打开达成的GetList()方法1看,转了1圈,再次来到了多少个DataView,

在从前的MDataTable达成绑定原理篇中,我们商量出要贯彻绑定,有三种办法:

再打开DataView,发现原本依旧继续了IEnumerable

壹种是落到实处IEnumerable接口,即当初走的DataReader方式实现的绑定。

唉,不折腾了,直接就上马IEnumerable好了:

另一种是促成IListSource接口,即走DataTable方式贯彻的绑定。

public interface IEnumerable
{
    [DispId(-4)]
    IEnumerator GetEnumerator();
}

怎么当初不兑现DataTable方式的绑定,不就完了,二种都援助~~-_-..现行反革命又得重临折腾IListSource接口的落到实处

先把接口继承了,要落到实处接口方法了,晕,不会写,总不可能写个抛非凡吧。。。。

 

 

二:长远DataTable绑定原理

又壹闪,既然DataView完结丰裕接口,看看人家怎么落到实处,照着模仿一下相应就大多了啊:

大家经过Reflector反编绎看下DataTable继承达成的接口:

public IEnumerator GetEnumerator()
{
    DataRowView[] array = new DataRowView[this.RowViewCache.Count];
    this.RowViewCache.CopyTo(array, 0);
    return array.GetEnumerator();
}

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

 

大概都是大家平日没用到的接口,不理先,大家关切IListSource怎么落到实处绑定的。

oh,竟然原来是搞了一份行数组,又来copy一下,之后回到调用数组的GetEnumerator()方法,

比方协调看一下IListSource要兑现的接口有几个方法:

算是意识前边一片光明,抄到便道了…

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

下节延续….

就四个,太容易了,接着大家要在DataTable
5000多行的代码中找到IListSource的贯彻,查找是最佳的主意:

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

}

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

GetList接口没事就赶回了个暗中认可视图,又要切进去看视图了。

图片 4图片 5

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,里面又是怎么认识出列名和分析出值的吗?

一:从DataTable中,大家看看一丝列名提取的相关方法,只是重回->DataRow
2:从DataRow中也看不到提取列名的章程,其主题的IList接口的相关兑现引出了->DataRowView
叁:DataRowView?是暧昧的六街三陌?一批继承的接口也是很不熟悉

 

回头继续查找:

改换思路继续大批量招来:换了无数重点字,搜汉语又搜E文

结果尽是一群自定义控件开发的东东,结果影像中在某一篇的googleE文的“网页快速照相”中发现一段E文,

原来的小说不知是哪了,上次都记念只可以打开快照,今后臆度能快速照相都没了,按想象翻译出来的中文差不离为:

DataTable能完结其绑定,是因为其达成了ICustomTypeDescriptor,从而获取其性质

 

偶滴神啊~能从宏伟的E文中,扫到多少个至关主要字不易于呀!!!

设若回转眼睛上边的DataRowView,就会发觉,正好,它达成了接口ICustomTypeDescriptor,
只是遥想当年,小编并不像未来写文这么冷清,作者当年早把Reflector关掉了,哪还记得DataRowView完成了ICustomTypeDescriptor,
何况ICustomTypeDescriptor对自个儿又是那么的面生,是那么的面生,…很不熟悉。。。

 

秘密已经出来了

ICustomTypeDescriptor接口,一个活动控件开发职员平日打交道的接口,对于我们却颇为不熟悉的接口

是它,正是它,正是它完结怎么样鉴定识别哪些是列名,哪些是列值。

 

 

3:浅入ICustomTypeDescriptor

那儿笔者透过大气的检索,试图找到相关的施用示范,因为那时本身不知晓DataRowView,借使知道,小编就毫无那么麻烦去搜小说了。

只要您寻找此接口,你会发觉一群的文章都是说移动控件开发,小编不怕从运动控件开发中很麻烦的挖了点示例完毕了。

可是此文就不走弯路了,直接解析DataRowView,对于 ICustomTypeDescriptor接口,有为数不少主意:

图片 6图片 7

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:System.ComponentModel.PropertyDescriptorCollection)(Attribute[]
attributes)

于是乎大家解析DataRowView对此接口的完成:

图片 8图片 9

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

接二连三浓密:

图片 10图片 11

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;
}

 

重大定位,只是重回1组:DataColumnPropertyDescriptor)

DataColumnPropertyDescriptor)是哪些?继续浓厚:

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

两行代码,那多少个base是什么?是PropertyDescriptor) ,达成很不难,把列名传过去就行了,至此,就停止了。

 

不清楚有个别许会看出此间,臆想本文大伙约等于扫下来,除非某天要使用到,不然只是忽悠下眼球了。

 

小结下实际实现ICustomTypeDescriptor接口方法:

一:继承达成接口方法
贰:重点落实GetProperties(Attribute[] attributes)方法
三:须要自定义属性描述类,而那自定义的脾气描述类须求后续自抽象基类PropertyDescriptor
肆:GetProperties重回的是自定义属性描述类的汇集

 

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

 

一:MDataTable继承IListSource接口落到实处

图片 12图片 13

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

 

2:MDataRow继承ICustomTypeDescriptor接口完毕

A:先达成自定义属性描述类

图片 14图片 15自定义属性描述类MDataProperty

internal class MDataProperty : System.ComponentModel.PropertyDescriptor
    {
        private MDataCell cell = null;
        public MDataProperty(MDataCell mdc, Attribute[] attrs)
            : base(mdc._CellStruct.ColumnName, attrs)
        {
            cell = mdc;
        }

        public override bool CanResetValue(object component)
        {
            return false;
        }

        public override Type ComponentType
        {
            get
            {
                return typeof(MDataCell);
            }
        }
        public override object GetValue(object component)
        {
            return ((MDataRow)component)[cell._CellStruct.ColumnName].Value;
           
        }

        public override bool IsReadOnly
        {
            get
            {
                return false;
            }
        }

        public override Type PropertyType
        {
            get { return cell._CellStruct.ValueType; }
        }

        public override void ResetValue(object component)
        {

        }

        public override void SetValue(object component, object value)
        {
            cell.Value = value;
        }

        public override bool ShouldSerializeValue(object component)
        {
            return true;
        }
              
        public override bool IsBrowsable
        {
            get
            {
                return true;
            }
        }
    }

 

B:完结主要措施GetProperties(Attribute[]
attributes)

图片 16图片 17

        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<实体>型就能够间接绑定了。

 

 

本文有点长,不知有多少人,看的明白,看的密切,估摸都以刷的1弹指上马拉到尾了图片 18~~~~