C# Dictionary绑定datagridview
我希望在dictionary变更时至少能显示出来所有的key,最好是显示key的值和value这个内部类里面的某个属性。
如果我尝试在每个更改dictionary的线程里面加上this.dataGridView.DataSource = tmpMap.ToList<KeyValuePair<string, InnerClass>>();会报跨线程错误。
求大神帮忙!!
BindingSource q = new BindingSource();
q.DataSource = this.tmpMap.Values;
this.dataGridView1.DataSource = q;
这个在初始化map后定义只能动态显示map里面数据的count,不过应该是某位用BindingSource比较好的大神能轻松化解我的问题!我觉得思路应该就该是在这儿 展开
你诶,离胜利只差一步了哟。
跨线程错误我就不说了。
你想要的是深入绑定,即能够绑定到元素项的内部属性,甚至内部属性的内部属性。
先说一下绑定原理,不论是dgv还是BindingSource的DataSource绑定,都需要数据获取者指明DataPropertyName,这要求绑定数据源:首先继承了IEnumrable<T>等一系列接口,其次T包含有至少可get的属性才可使用绑定。对于你的情况,如果使用BindingSource直绑Dictionary,你的泛型T就是KeyValuePair<TKey,TValue>,其拥有公开的属性Key、Value、Count等等,此时数据获取者要填写的DataPropertyName可以是“Key”,“Value”,“Count”等等。
当然我们的需求是花样百出的,还是以你的情况为例,难免会出现Value和Key是自己定义的类型,此时如果不改DataPropertyName,你得到的只会是该类型的名称字符串。想要绑定到自定义类型的内部甚至更内部,有至少二种办法:
一、继承系统的BindingSource,overide及新增一些方法,可以让你在使用MyBindingSource mbs=new MyBindingSource(...)时直接指明你需要绑定的内部元素。这个过程开销很小但是编写有一定难度,需要在BindingSource内部重新维护一个合适你需要的绑定元素列表,并且需要处理绑定属性名的问题。此技术在大型项目中比较多用,好处是一次改完哪里都能用,而且可以支持双向绑定,允许反向编辑真实的数据源。有兴趣的话可以PM我我写个简单的给你。
二、修改提供给BindingSource或者dgv.DataSouce的数据源,也就是直接抽取内部属性出来构建一个新的绑定数据源。比较适合针对某个特定表的绑定,也是最容易实现的。当然,因为你是新构建了用于显示的数据源,只能支持单向绑定咯。
假定你的InnerClass是这样写的:
public class MyData
{
public string C1 { get; set; }
public string C2 { get; set; }
public string C3 { get; set; }
}
如果需要用两列分别绑定Dictionary<string,MyData> dic的Key和MyData.C1,一行搞定:
dataGridView1.DataSource=(from i in dic select new{i.Key,i.MyData.C1}).ToList();
本质上就是遍历字典,把每一个键值对的Key和Value.C1都抽出来做成新字典然后转列表。
如果不熟悉Linq,也可以自己写一个抽取数据的小方法每次绑定前转换下。
嗯,刚才我同事也给了个很中二的办法:重写dataGridView。通过重写绑定相关的方法,可以让DataGridView能够识别形如"Value.C1"甚至“Value.C1.Length"这样的DataProperyName并且在绑定事件中能够通过反射查找Value内部是否存在C1属性,如果该属性存在则将其呈现。
这个可以一试,目测难度较大。
和同事小聊了下我又想起一个另类的办法- -|
我们知道不管你绑的是什么值,想在界面上看到都有一个转换过程。这里DataGridView描绘每个含绑定的单元格时都会把对应的数据源中的绑定元素的ToString()值拿来呈现。如果你只有一列需要绑定到InnerClass的C1属性,我们可以这样取巧:
首先dgv里的两列的DataPropertyName仍然写的是”Key“和"Value”,这样第二列绑到的是一个InnerClass对象,只不过其显示出来的ToString()是形如“MyNamespace.InnerClass”这样的类名字符串,如果我们重写InnerClass的ToString()方法呢?测试完发现一切OK。也只需要在InnerClass里加一句:
public override string ToString()
{
return C1;
}
以上四种方案你挑着用吧。我相信如果你愿意投一点时间多从其他角度看问题的话,你会找到更多解决方案的。为了生活有时我们不得不只抓效率抓进度,但闲暇时做点小研究其实也是挺惬意的一个事情,并非是得不偿失~
还有什么问题可PM我。
您简直是我的superstar,我差点就放弃了!
加油!