Chr*_*ray 28 c# data-binding winforms
我有一组"动态数据",我需要绑定到GridControl.到目前为止,我一直在使用标准的DataTable类,它是System.Data命名空间的一部分.这工作得很好,但我被告知我不能使用它,因为它对于客户端和服务器之间的网络序列化太重了.
所以我认为我可以通过简单地使用List<Dictionary<string, object>>List表示行集合的类型来轻松复制DataTable类的"简化"版本,并且每个Dictionary表示一行,其中列名称和值为KeyValuePair类型.我可以设置Grid以使列DataField属性与Dictionary中的键匹配(就像我为DataTable的列名所做的那样).
但是做完之后
gridControl.DataSource = table;
gridControl.RefreshDataSource();
Run Code Online (Sandbox Code Playgroud)
网格没有数据......
我想我需要实施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();
Run Code Online (Sandbox Code Playgroud)
Mar*_*ell 64
欢迎来到System.ComponentModel的精彩世界..NET的这个黑暗角落非常强大,但非常复杂.
谨慎一点; 除非你有足够的时间来做这件事 - 你可以用你喜欢的任何机制来简单地序列化它,但是DataTable在每一端将它重新水化成一个......以下内容不适合那些胆小的人;-p
首先 - 数据绑定(对于表)对列表(IList/ )起作用IListSource- 所以List<T>应该没问题(编辑:我误读了一些东西).但它不会理解你的词典实际上是列...
要获得一个假装有列的类型,您需要使用自定义PropertyDescriptor实现.有几种方法可以执行此操作,具体取决于列定义是否始终相同(但在运行时确定,即可能来自配置),或者它是否根据使用情况而更改(例如每个DataTable实例如何具有不同的列).
对于"每个实例"自定义,你需要看一下ITypedList- 这个野兽(除此之外实现IList)有一个有趣的任务,即呈现表格数据的属性......但它并不孤单:
对于"每类型"自定义,您可以查看TypeDescriptionProvider- 这可以建议类的动态属性...
...或者你可以实现ICustomTypeDescriptor- 但这仅在非常偶然的情况下使用(用于列表)(对象索引器(public object this[int index] {get;}")和绑定点列表中的至少一行).(这个接口更有用绑定离散对象时 - 即不是列表).
实施ITypedList和提供PropertyDescriptor模型是一项艰苦的工作......因此,它只是偶尔进行.我对它很熟悉,但我不会只为笑而做...
这是一个非常非常简化的实现(所有列都是字符串;没有通知(通过描述符),没有验证(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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
21808 次 |
| 最近记录: |