首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >数据绑定动态数据

数据绑定动态数据
EN

Stack Overflow用户
提问于 2009-05-19 11:35:35
回答 1查看 23.9K关注 0票数 28

我有一组需要绑定到GridControl的“动态数据”。到目前为止,我一直在使用属于System.Data名称空间的标准DataTable类。这工作得很好,但是我被告知我不能使用它,因为它对于客户端和服务器之间的网络序列化来说太重了。

因此,我想我可以简单地复制DataTable类的“精简”版本,只需拥有一种List<Dictionary<string, object>>类型,列表表示行的集合,每个字典表示一行,并将列名和值作为KeyValuePair类型。我可以设置网格,使列的DataField属性与字典中的键的属性相匹配(就像我对数据表的列名所做的那样)。

但是在做完之后

代码语言:javascript
复制
gridControl.DataSource = table;
gridControl.RefreshDataSource();

网格没有数据...

我认为我需要实现IEnumerator -在这方面的任何帮助都将非常感谢!

示例调用代码如下所示:

代码语言:javascript
复制
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();
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2009-05-19 11:43:47

欢迎来到奇妙的System.ComponentModel世界。.NET的这个黑暗角落非常强大,但也非常复杂。

提醒一句;除非你有足够的时间来做这件事--你可以简单地用你喜欢的任何机制来序列化它,但是在每一端都将它恢复为DataTable……接下来的事不适合胆小鬼

首先,数据绑定(用于表)适用于列表(IList/IListSource) -所以List<T>应该没问题(编辑:我读错了什么)。但它不会理解你的字典实际上是列...

要获得假装具有列的类型,您需要使用定制的PropertyDescriptor实现。有几种方法可以做到这一点,这取决于列定义是否总是相同(但在运行时确定,即可能是从配置中确定的),还是根据使用情况而变化(就像每个DataTable实例可以具有不同的列一样)。

对于“每个实例”的定制,你需要看看ITypedList --这个野兽(除了IList之外实现)有一个有趣的任务,那就是呈现表格数据的属性……但它并不孤单:

对于“每种类型”的定制,你可以看看TypeDescriptionProvider -这可以建议一个类的动态属性...

...or你可以实现ICustomTypeDescriptor -但这只在非常的情况下使用(对于列表)(一个对象索引器(public object this[int index] {get;}")和列表中至少一行在绑定点)。(这个接口在绑定离散对象时更有用--即不绑定列表)。

实现ITypedList并提供PropertyDescriptor模型是一项艰巨的工作……因此,这只是非常偶然的事情。我对它相当熟悉,但我不会仅仅为了好玩而这么做……

这是一个非常非常简单的实现(所有列都是字符串;没有通知(通过描述符),没有验证(IDataErrorInfo),没有转换(TypeConverter),没有额外的列表支持(IBindingList/IBindingListView),没有抽象(IListSource),没有其他元数据/属性,等等):

代码语言:javascript
复制
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;
        }
    }
}
票数 64
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/882214

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档