数据绑定dynamic数据
我有一组“dynamic数据”,我需要绑定到GridControl。 直到现在,我一直在使用属于System.Data命名空间的标准DataTable类。 这工作正常,但我已经被告知我不能使用这个,因为它太重的客户端和服务器之间的networking序列化。
所以我想我可以简单地复制DataTable类的“简化”版本,只需要一个List<Dictionary<string, object>>
,List代表行的集合,每个Dictionary代表一行列名称和值作为KeyValuePairtypes。 我可以设置网格的DataField属性来匹配Dictionary中的键(就像我为DataTable的列名所做的那样)。
但是做完之后
gridControl.DataSource = table; gridControl.RefreshDataSource();
网格没有数据…
我想我需要实现IEnumerator
– 任何帮助,将不胜感激!
示例调用代码如下所示:
var table = new List<Dictionary<string,object>>(); var row = new Dictionary<string, object> { {"Field1", "Data1"}, {"Field2", "Data2"}, {"Field3", "Data3"} }; table.Add(row); gridControl1.DataSource = table; gridControl1.RefreshDataSource();
欢迎来到System.ComponentModel的精彩世界。 .NET的这个黑暗angular落非常强大,但非常复杂。
谨慎的一句话; 除非你有这么多的时间,否则你可能会简单地用任何你感到满意的机制序列化它,但是在每一端将它重新加水到一个DataTable
中……接下来的事情不是为了胆小鬼; p
首先 – 数据绑定(对于表)工作列表 ( IList
/ IListSource
) – 所以List<T>
应该罚款(编辑:我误读了一些东西)。 但是它不会理解你的字典实际上是列…
要获得一个types假装有列你需要使用自定义的PropertyDescriptor
实现。 有几种方法可以做到这一点,这取决于列定义是否总是相同(但是在运行时(也就是从configuration文件中确定)),还是每个用户更改(如每个DataTable
实例如何可以有不同的列)。
对于“每个实例”定制,您需要查看ITypedList
– 这个野兽( 除了 IList
之外实现)具有呈现表格数据的属性的有趣任务…但并不是单独的:
对于“每种types”定制,你可以看看TypeDescriptionProvider
– 这可以build议一个类的dynamic属性…
…或者你可以实现ICustomTypeDescriptor
– 但是这仅仅在非常偶然的情况下(一个对象索引器( public object this[int index] {get;}
)被使用,并且在列表中至less有一行绑定点)(这个接口在绑定离散对象时非常有用 – 即不是列表)。
实现ITypedList
,并提供PropertyDescriptor
模型是艰苦的工作…因此,它只是偶尔做。 我对它很熟悉,但是我不会为了笑而去做。
这里有一个非常简单的实现(所有列都是string,没有通知(通过描述符),没有validation( IDataErrorInfo
),没有转换( TypeConverter
),没有额外的列表支持( IBindingList
/ IBindingListView
),没有抽象( IListSource
)其他元数据/属性等):
using System.ComponentModel; using System.Collections.Generic; using System; using System.Windows.Forms; static class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); PropertyBagList list = new PropertyBagList(); list.Columns.Add("Foo"); list.Columns.Add("Bar"); list.Add("abc", "def"); list.Add("ghi", "jkl"); list.Add("mno", "pqr"); Application.Run(new Form { Controls = { new DataGridView { Dock = DockStyle.Fill, DataSource = list } } }); } } class PropertyBagList : List<PropertyBag>, ITypedList { public PropertyBag Add(params string[] args) { if (args == null) throw new ArgumentNullException("args"); if (args.Length != Columns.Count) throw new ArgumentException("args"); PropertyBag bag = new PropertyBag(); for (int i = 0; i < args.Length; i++) { bag[Columns[i]] = args[i]; } Add(bag); return bag; } public PropertyBagList() { Columns = new List<string>(); } public List<string> Columns { get; private set; } PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors) { if(listAccessors == null || listAccessors.Length == 0) { PropertyDescriptor[] props = new PropertyDescriptor[Columns.Count]; for(int i = 0 ; i < props.Length ; i++) { props[i] = new PropertyBagPropertyDescriptor(Columns[i]); } return new PropertyDescriptorCollection(props, true); } throw new NotImplementedException("Relations not implemented"); } string ITypedList.GetListName(PropertyDescriptor[] listAccessors) { return "Foo"; } } class PropertyBagPropertyDescriptor : PropertyDescriptor { public PropertyBagPropertyDescriptor(string name) : base(name, null) { } public override object GetValue(object component) { return ((PropertyBag)component)[Name]; } public override void SetValue(object component, object value) { ((PropertyBag)component)[Name] = (string)value; } public override void ResetValue(object component) { ((PropertyBag)component)[Name] = null; } public override bool CanResetValue(object component) { return true; } public override bool ShouldSerializeValue(object component) { return ((PropertyBag)component)[Name] != null; } public override Type PropertyType { get { return typeof(string); } } public override bool IsReadOnly { get { return false; } } public override Type ComponentType { get { return typeof(PropertyBag); } } } class PropertyBag { private readonly Dictionary<string, string> values = new Dictionary<string, string>(); public string this[string key] { get { string value; values.TryGetValue(key, out value); return value; } set { if (value == null) values.Remove(key); else values[key] = value; } } }