2017-04-14 27 views
1

當您設置List或甚至更好的BindingList作爲DataGridView的源時,它將獲取屬性列表並使用它們來生成列。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>它們都不會將動態成員綁定到列。我甚至嘗試創建一個繼承DynamicObject的類,並重寫TryGetMember和TrySetMember。

我覺得我正在旋轉我的車輪,並忽略了一個簡單的解決方案。也許有一些技巧使用我在這裏失蹤的Dictionary和Linq。

注意事項:我正在收集數據,總結並顯示它。一旦顯示數據,我不需要添加或刪除數據。我會盡力篩選和排序。但是,一旦我弄清楚如何展示它,我會穿過那座橋。

我的例子示出了簡單的已知值和類型,但我的實際的源數據將是較不可預測並且從JSON使用Newtonsoft JSON用結構解析如下:

[ { 「match_number」:1 , 「SET_NUMBER」:1, 「鍵」: 「2017onbar_f1m1」, 「score_breakdown」:{ 「藍色」:{ 「totalPoints」:236, 「foulCount」:1, 「adjustPoints」:0, 「加班」:真 }, 「紅」:{ 「totalPoints」:236, 「foulCount」:1, 「adjustPoints」:0, 「加班」:真 } }, 「teammembers」:{ 「藍色」:{ 「團隊」:[ 「的member1」, 「member2」, 「member3」 ] }, 「紅色」:{ 「團隊」:[ 「member4」, 「member5」, 「member6」 ] } } }]

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

+0

爲datagridview使用'dynamic'的目的是什麼? 'DataGridView.DataSource'是所有其他強類型對象的集合。 – Fabio

+0

看起來像XY問題,你可以顯示你從那個來源得到什麼樣的數據(格式)? – Fabio

+0

源數據有點大,但源代碼是使用Newtonsoft.JSON轉換的JSON。一些結構將保持不變,但有些會有所不同。 – Prdufresne

回答

0

嘗試中的BindingList轉換成數據表

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; 

    } 
+0

我會試一試。謝謝。 – Prdufresne

+0

謝謝@Jury_Golubev。我想你已經把我推向了與我計劃不同的方向,但我認爲這個選擇最終會更好。使用ExpandoObject可能是錯誤的方法,因爲我正在嘗試做的事情,我認爲使用List of Dictionaries和一個方法將它們轉換爲DataTable表示會更好。更乾淨。謝謝! – Prdufresne

0

如果給定的數據源時是某種類型的(未的Type實例)DatagridView.DataSource設定器將使用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"); 

但再次 - 如果您在編譯時知道屬性名稱,爲什麼不爲它創建類?

+0

在我提供的相同代碼中,我只是添加了一些示例數據,但在我的實際應用程序中,我正在解析JSON對象中的數據,因此直到運行時纔會知道這些屬性。我曾嘗試創建一個包含內部字典和自定義GetPropoerties方法的類,但這似乎不適用於我,可能是因爲我錯誤地格式化了Ilist – Prdufresne