2017-04-14 4 views
1

ListまたはDataGridViewのソースとしてBindingListを設定すると、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がプロパティのコレクションを取得することができるメソッドがないので、それが推測しています。

上記のコードサンプルで、同じコードを実行してExpandoObjectをMyCustomClassに置き換えた場合、DataGridViewには正しく設定されます。

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

しかし、変更する可能性のあるソースからデータを読み込んでいるため、動的クラスを使用する必要があります。私はバインディングリストBindigListを含むいくつかのメソッドを試しましたが、どれも動的メンバーを列にバインドしません。私は、TryGetMemberとTrySetMemberのオーバーライドを使ってDynamicObjectを継承するクラスを作成しようとしました。

私は私の車輪を回転させ、簡単な解決策を見過ごしているように感じる。おそらく、私がここで紛失している辞書とLinqを使っていくつかのトリックがあります。

警告:私はデータを収集し、要約して表示しています。表示されたらデータを追加または削除する必要はありません。私はそれをフィルタリングしてソートしようとしています。私はそれを見せる方法を見つけたら、私はその橋を渡ります。

[ { 「match_numberを」:

私の例は、単純な既知の値と型を示しているが、私の実際のソースデータが少ない予測可能となり、次のように構造のNewtonsoft JSONを使用して、JSONから解析された1 、 "SET_NUMBER":1、 "キー": "2017onbar_f1m1"、 "score_breakdown":{ "青":{ "totalPoints":236、 "foulCount":1、 "adjustPoints":0、 "overtime":true }、 "red":{ "totalPoints":236、 "foulCount":1、 "adjustPoints":0、 "残業":真 } }、 "teammembers":{ "青":{ "チーム":[ "MEMBER1"、 "member2"、 "member3" ] }、 "赤":{ "チーム":[ "member4"、 "member5"、 "member6" ] } } }]

ただし、score_breakdownフィールドは異なります。

+0

DataGridviewに 'dynamic'を使用する目的は何ですか?他の強い型付きオブジェクトの 'DataGridView.DataSource' wilコレクションです。 – Fabio

+0

XY問題のように見えますが、そのソースからどのような種類のデータ(形式)を表示できますか? – Fabio

+0

ソースデータは少し大きいですが、ソースはNewtonsoft.JSONを使用して変換されたJSONです。構造のいくつかは一定ですが、いくつかは変化します。 – Prdufresne

答えて

0

は、所与のデータソースは、いくつかのタイプ(Typeのないインスタンス)DatagridView.DataSourceセッターのインスタンス列を生成するために使用される、プロパティを取得するためsource.GetType().GetProperties()を使用するとき場合にデータテーブル

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を使うのはおそらく間違ったアプローチです。私は、DataTableとして表現するためにそれらを変換するメソッドで辞書のリストを使う方が良いと思います。とても清潔です。ありがとうございました! – Prdufresne

0

にあなたするBindingListを変換してみてください。

問題は、コンパイル時にプロパティの名前を知っているので、あなたは、C#の新機能を使用してタプル

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

を作成することができ、あなたのケースでタイプExpandoObjectは空のコレクションを返すこと

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

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

ですが再度 - コンパイル時にプロパティ名を知っていれば、そのクラスを作成しないのはなぜですか?

+0

私が提供したのと同じコードで、サンプルデータを追加するだけですが、実際のアプリケーションでは、JSONオブジェクトからデータを解析しているため、実行時までプロパティがわかりません。内部ディクショナリとカスタムGetPropoertiesメソッドを使ってクラスを作成しようとしましたが、それはおそらく私がIlistを間違ってフォーマットしていたためにうまくいかなかったようです – Prdufresne

関連する問題