首页 新闻 会员 周边 捐助

关于winform数据绑定的一个疑问

0
悬赏园豆:40 [已解决问题] 解决于 2013-12-13 11:14

某些控件(如datagridview)会提供一个DataSource的属性,这个属性是Object类型的,但是如果赋值一个String或Int等类型肯定是完成不了绑定功能的,F12看了下这个DataSource属性,发现有一个特性AttributeProviderAttribute来修饰该属性,我查了下MSDN,英文不好,看不懂,后来又看中文版MSDN:http://msdn.microsoft.com/zh-cn/library/system.componentmodel.attributeproviderattribute(v=vs.85).aspx

 

里面有这么2句话:“之所以这样,是为了让此属性可以接受多种类型的输入。遗憾的是,这样做并未提供添加元数据以描述属性特性的通用方法”。第一句看懂了,第二句到底想表达个什么呢?还有他说“为了让此属性可以接受多种类型的输入”而把DataSource定义为Object,可是只有传入一个IListSource类型的数据才能完成绑定,“为了让此属性可以接受多种类型的输入”到底有什么用呢,谢谢。

如下是DataSource属性的定义:

        //
        // 摘要: 
        //     获取或设置 System.Windows.Forms.DataGridView 所显示数据的数据源。
        //
        // 返回结果: 
        //     包含 System.Windows.Forms.DataGridView 要显示的数据的对象。
        //
        // 异常: 
        //   System.Exception:
        //     数据源中发生错误,System.Windows.Forms.DataGridView.DataError 事件没有处理程序,或者处理程序已将 System.Windows.Forms.DataGridViewDataErrorEventArgs.ThrowException
        //     属性设置为 true。 通常情况下,可将该异常对象强制转换为类型 System.FormatException。
        [AttributeProvider(typeof(IListSource))]
        [DefaultValue("")]
        [RefreshProperties(RefreshProperties.Repaint)]
        public object DataSource { get; set; }

 以下是这个我想知道用途的特性的定义:

    // 摘要: 
    //     启用特性重定向。 此类不能被继承。
    [AttributeUsage(AttributeTargets.Property)]
    public class AttributeProviderAttribute : Attribute
    {
        // 摘要: 
        //     用给定的类型名称初始化 System.ComponentModel.AttributeProviderAttribute 类的新实例。
        //
        // 参数: 
        //   typeName:
        //     要指定的类型的名称。
        //
        // 异常: 
        //   System.ArgumentNullException:
        //     typeName 为 null。
        public AttributeProviderAttribute(string typeName);
        //
        // 摘要: 
        //     用给定的类型初始化 System.ComponentModel.AttributeProviderAttribute 类的新实例。
        //
        // 参数: 
        //   type:
        //     要指定的类型。
        //
        // 异常: 
        //   System.ArgumentNullException:
        //     type 为 null。
        public AttributeProviderAttribute(Type type);
        //
        // 摘要: 
        //     用给定的类型名称和属性名称初始化 System.ComponentModel.AttributeProviderAttribute 类的新实例。
        //
        // 参数: 
        //   typeName:
        //     要指定的类型的名称。
        //
        //   propertyName:
        //     将为其检索特性的属性的名称。
        //
        // 异常: 
        //   System.ArgumentNullException:
        //     typeName 为 null。
        //
        //   System.ArgumentNullException:
        //     typeName 为 null。
        public AttributeProviderAttribute(string typeName, string propertyName);

        // 摘要: 
        //     获取将为其检索特性的属性的名称。
        //
        // 返回结果: 
        //     将为其检索特性的属性的名称。
        public string PropertyName { get; }
        //
        // 摘要: 
        //     获取传入构造函数的程序集限定类型名称。
        //
        // 返回结果: 
        //     构造函数中指定的类型的程序集限定名称。
        public string TypeName { get; }
    }
问题补充:

我分析的可能有问题,关键点是AttributeProviderAttribute这个特性起什么作用呢

会长的主页 会长 | 专家六级 | 园豆:12463
提问于:2013-12-12 15:46
< >
分享
最佳答案
1

事实是,通常控件都会提供一个 DataBindings 属性,而支持集和类型的控件才有 DataSource 属性。

我建议你还是写点代码,不写代码,你确实不知道有什么用。

收获园豆:30
Launcher | 高人七级 |园豆:45050 | 2013-12-12 16:00

高人就是高人。高人,我写代码用了一下DataBindings,以前都是拖一个bingingsource进来,然后右键控件-》属性-》把DataBindings下面的tag,text选一下,或者是把DataSource(如果有这个属性的话)赋值bingingsource对象,从来没去看过自动生成的代码。不过我还是不明白Datagridview控件的DataSource属性为什么不直接定义为IListSource类型,定义成Object有什么好处呢,谢谢

比如我自己开发了一个控件,也要绑定数据,我提供了一个DataSource属性,DataSource属性值必须是实现了IListSource接口的类的实例,当然我定义为类型Object也不错,只是如果传入的参数没有实现IListSource接口就不会发生数据绑定行为,但是我什么不直接把DataSource的类型定义为IListSource呢。

-------------补充--------------

我试了下把List<自定义类> 传递给datagridview控件的DataSource属性,照样能绑定,而List<T>貌似并没有实现IListSource。那个特性AttributeProviderAttribute起什么作用呢

会长 | 园豆:12463 (专家六级) | 2013-12-12 16:50

@会长: 这样吧,我再告诉你一种 DataGridView 的绑定方式:

DataSet ds = new DataSet();

BindingSource bs = new BindingSource();

bs.DataSource = ds;

bs.DataMember = "Table1";

DataGridView.DataSource = bs;

看到了吗?可以绑定 DataSet ,然后通过 bs.DataMember = "Table1" 来指定是 DataSet 中的哪一张表。

Launcher | 园豆:45050 (高人七级) | 2013-12-12 17:51

@Launcher: 我平时也是这么用的。我现在只想搞清楚DataSource属性上有个特性AttributeProviderAttribute到底起什么作用呢

会长 | 园豆:12463 (专家六级) | 2013-12-12 17:59

@会长: DataGridView 的 DataSource 需要接受 BindingSource 类型的参数,这样 DataSource 就不能只接受 IListSource 类型,对不对? BindingSource 的 DataSource 用于绑定 TextBox 的 Text 属性时,需要接受 string 类型,这样它就不能只接受 IListSource 类型,对不对?

如果都对的话,是不是将 DataSource 定义为 Object ,就印证了这句话:之所以这样,是为了让此属性可以接受多种类型的输入,对不对?

那么再回头来回答你的第一个问题:到底有什么用呢

是不是就是把 MSDN 上的话再重复一遍:为了让此属性可以接受多种类型的输入

那么再来看 MSDN 对 AttributeProviderAttribute 的解释:对于需要元数据的类型转换器、UI 类型编辑器和其他服务。元数据是指的额外的用于描述 DataSource 属性的数据。那么它是干什么用的呢?自己看 MSDN 的原话,“需要元数据的类型转换器、UI 类型编辑器和其他服务”,简单翻译下,就是说有些“类型转换器、UI 类型编辑器和其他服务”需要属性提供额外的信息才能够完成工作。用在 DataSource 属性这里就是,某些“类型转换器、UI 类型编辑器和其他服务”需要 DataSource 提供额外的信息才能够完成工作,比如你通过“UI 类型编辑器”来为 DataSource 绑定到数据源时,这时候特定的“类型转换器(TypeConverter 的派生类)”就会尝试将 DataSource 转换成 IListSource 类型,如果能够转换,就会显示出绑定 IListSource 类型的属性用于编辑,如果不能转换,就按照 Object 设置。

 

Launcher | 园豆:45050 (高人七级) | 2013-12-13 09:58

@Launcher: 虽然你是高人,但是能不能不用这种盛气凌人的表达方式和别人说话,大不了不说话算了。

会长 | 园豆:12463 (专家六级) | 2013-12-13 11:13
其他回答(1)
0

用Object, 理论上说可以用反射秒杀所有的类型.

 

比如你绑定到List<MyClass>上, 那么可以用DateMember指定用MyClass的哪一个属性, 而你只要写上这个属性的名字就可以了.

 

毫无疑问, 为了实现这个功能, 微软会使用反射.

收获园豆:10
undefined | 园豆:898 (小虾三级) | 2013-12-12 17:55

那DataSource属性上有个特性AttributeProviderAttribute到底起什么作用呢

支持(0) 反对(0) 会长 | 园豆:12463 (专家六级) | 2013-12-12 18:00

比如这样: 

DataGridView.AutoGenerateColumns = true;
DataGridView.DataSource = new object[] { new { Name = "Arthas" ,age=100}, new { Name = "Bill", age=1000 } }.ToList();

支持(0) 反对(0) undefined | 园豆:898 (小虾三级) | 2013-12-12 18:10

@undefined: 那这个AttributeProviderAttribute特性起什么作用呢

支持(0) 反对(0) 会长 | 园豆:12463 (专家六级) | 2013-12-12 18:12

@会长: 好像是给winform设计器用的.具体我不是很记得了. 大概是这么个场景:你看, 你在winform设计器里面可以用下拉框直接给DataSource选一个值对吧?微软怎么没有把整个工程的所有Object都列在那而是单单列了你拉过去的BindingSource呢?似乎就是通过这些Attribute告诉微软的。 具体你可以自己研究下。 我很久没碰过winform了。 以前在葡萄城倒是经常看看这些东西。

支持(0) 反对(0) undefined | 园豆:898 (小虾三级) | 2013-12-12 18:20

@undefined: 哇塞,有道理,可能是,不过我到msdn也没看懂,不知道是我理解能力差,还是他表达的不清楚,这问题我暂时不去研究它了,呵呵。你以前在葡萄城干过,貌似正在招聘,这家公司感觉怎么样呢

支持(0) 反对(0) 会长 | 园豆:12463 (专家六级) | 2013-12-12 18:35

@会长:  参考System.ComponentModel.ReflectPropertyDescriptor 类的

FillAttributes(IList attributes) 方法的实现.  这个AttributeProviderAttribute 其实是一个"替身"角色.

支持(0) 反对(0) -Neil | 园豆:207 (菜鸟二级) | 2013-12-13 09:32
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册