当您设置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&gt;其中没有一个会将动态成员绑定到列。我甚至尝试使用TryGetMember和TrySetMember的覆盖创建一个继承DynamicObject的类。
我觉得我在旋转车轮,忽略了一个简单的解决方案。也许使用我在这里缺少的词典和Linq的一些技巧。
警告:我正在收集数据,汇总数据并显示数据。我不需要在显示数据后添加或删除数据。我会尝试过滤和排序它。不过,一旦我弄清楚如何展示它,我就会越过那座桥。
我的示例显示了简单的已知值和类型,但我的实际源数据将不太可预测,并且使用Newtonsoft JSON从JSON解析,结构如下:
[ { &#34; match_number&#34;:1, &#34; set_number&#34;:1, &#34; key&#34;:&#34; 2017onbar_f1m1&#34;, &#34; score_breakdown&#34;:{ &#34;蓝&#34;:{ &#34; totalPoints&#34;:236, &#34; foulCount&#34;:1, &#34; adjustPoints&#34;:0, &#34;加班&#34;:是的 }, &#34; red&#34;:{ &#34; totalPoints&#34;:236, &#34; foulCount&#34;:1, &#34; adjustPoints&#34;:0, &#34;加班&#34;:是的 } }, &#34; teammembers&#34;:{ &#34;蓝&#34;:{ &#34;团队&#34;:[ &#34;的member1&#34 ;, &#34; member2&#34 ;, &#34; member3&#34; ] }, &#34; red&#34;:{ &#34;团队&#34;:[ &#34; member4&#34 ;, &#34; member5&#34 ;, &#34; member6&#34; ] } } }]
但是,score_breakdown字段会有所不同。
答案 0 :(得分:0)
尝试将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;
}
答案 1 :(得分:0)
如果给定的数据源是某种类型的实例(不是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" );
但是再次 - 如果您在编译时知道属性名称,为什么不为它创建一个类?