繁体   English   中英

DataGridView如何获取类中的属性列表?

[英]How does DataGridView get the list of properties in a class?

当您设置List或者更好的是将BindingList作为DataGridView的源时,它会获取属性列表并使用它们来生成列。

如果我执行以下操作:

        StatsList = new BindingList<ExpandoObject>();

        // Add seed record to generate columns in DataGridView
        dynamic ds = new ExpandoObject();

        ds.key = "0000";
        ds.Name = "Bob";
        ds.Number = "2255442";

        ds.key = "0001";
        ds.Name = "Nathan";
        ds.Number = "1217479";

        StatsList.Add(ds);

        dgvListView.DataSource = StatsList;

什么都没发生。 没有任何列或行被添加到DataGridView。 我猜这是因为缺少一个允许DataGridView获取属性集合的方法。

如果我运行相同的代码,但在上面的代码示例中使用MyCustomClass替换ExpandoObject,如下所定义,DataGridView将填充正常。

public class MyCustomClass
{
    public string key { get; set; }
    public string name { get; set; }
    public string number { get; set; }
}

但是,由于我从可能发生变化的源读取数据,因此我需要使用动态类。 我尝试了很多方法,包括BindingList BindigList>都没有将动态成员绑定到列。 我甚至尝试使用TryGetMember和TrySetMember的覆盖创建一个继承DynamicObject的类。

我觉得我正在转动轮子,忽略了一个简单的解决方案。 也许有一些技巧使用我在这里缺少的Dictionary和Linq。

注意事项:我正在收集数据,总结并显示数据。 一旦显示数据,我就不需要添加或删除数据。 我会尝试过滤和排序它。 不过,一旦我弄明白如何展示它,我就会越过那座桥。

我的示例显示了简单的已知值和类型,但我的实际源数据将不太可预测,并且使用Newtonsoft JSON从JSON解析,结构如下:

[{“match_number”:1,“set_number”:1,“key”:“2017onbar_f1m1”,“score_breakdown”:{“blue”:{“totalPoints”:236,“foulCount”:1,“adjustPoints”:0, “加班”:真实},“红色”:{“totalPoints”:236,“foulCount”:1,“adjustPoints”:0,“加班”:真}},“teammembers”:{“blue”:{“团队“:[”member1“,”member2“,”member3“]},”red“:{”teams“:[”member4“,”member5“,”member6“]}}}]

但是,score_breakdown字段会有所不同。

尝试将BindingList转换为DataTable

    protected void Page_Load(object sender, EventArgs e)
    {
        var StatsList = new BindingList<ExpandoObject>();

        // Add seed record to generate columns in DataGridView
        dynamic ds = new ExpandoObject();

        ds.key = "0000";
        ds.Name = "Bob";
        ds.Number = "2255442";

        dynamic ds2 = new ExpandoObject();

        ds2.key = "0001";
        ds2.Name = "Nathan";
        ds2.Number = "1217479";

        StatsList.Add(ds);
        StatsList.Add(ds2);


        GridView1.DataSource = ExpandoListToDataTable(StatsList);

        GridView1.DataBind();
    }

    protected DataTable ExpandoListToDataTable(BindingList<ExpandoObject> d)
    {
        var dt = new DataTable();

        foreach (var a in d)
        {
            foreach (var key in ((IDictionary<string, object>)a).Keys)
            {
                if (!dt.Columns.Contains(key))
                {
                    dt.Columns.Add(key);
                }
            }

            dt.Rows.Add(((IDictionary<string, object>)a).Values.ToArray());
        }

        return dt;

    }

如果给定的datasource是某种类型的实例(不是Type实例), DatagridView.DataSource setter将使用source.GetType().GetProperties()来检索属性,这些属性将用于生成列。

问题是在你的情况下类型ExpandoObject将返回空集合

dynamic ds = new ExpandoObject();
ds.key = "0000";
ds.Name = "Bob";
ds.Number = "2255442";

ds.GetType().GetProperties() // return empty collection

因为您在编译时知道属性的名称,所以可以使用C#的新功能并创建元组

var ds = ( key: "0000", Name: "Bob", Number: "2255442" );

但是再次 - 如果您在编译时知道属性名称,为什么不为它创建一个类?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM