2013-08-26 9 views
11

でデータグリッドを埋める私はdynamicly埋まるする必要があるデータグリッドを持っています。動的な列

tablelayoutは次のようである:

id | image | name | Description | Name-1 | Name-N 

第4列は、他のものは動的で静的です。ユーザーは、必要な数のユーザーを追加できます。

私は、テーブルに隣同士にそれらを置くことによって、複数のユーザーのデータを比較してみてください。

今私は、動的に生成列の名前と静的な列を地下鉄Filles方法をcontaines whitchリストボックスを持っています。また、各ユーザーのデータを読み込むこともできます。今私は1つの大きなテーブルにそれらをマージする必要があります。

主な問題は、今ある:「Userdataの」と1つのDataGrid内の静的コンテンツを配置する方法。

+0

この情報を表示する唯一の方法はありますか? –

+0

あなたの求めるものがわかりません。 – Wr4thon

+0

ヨハネスは私の答えを見るので、なぜ私はそれを求めているのか分かります。 –

答えて

20

これを行うには、少なくとも3つの方法があります:

  1. がCustomTypeDescriptor

    を使用してください*のItemsSourceとしてのDataTableを使用して、コードビハインド

  2. から手動でDataGridの列を変更します。 *シンプル

にお勧め

第一のアプローチ:実行時にDataGridの列を生成するために使用コードビハインド。これは実装が簡単ですが、特にあなたがMVVMを使用している場合は、ちょっとハックしているかもしれません。だから、固定列を使用してデータグリッドを持っていると思います:

<DataGrid x:Name="grid"> 
    <DataGrid.Columns> 
     <DataGridTextColumn Binding="{Binding id}" Header="id" /> 
     <DataGridTextColumn Binding="{Binding image}" Header="image" /> 
    </DataGrid.Columns> 
</DataGrid> 

あなたの「名前」は準備ができている場合、その列を削除/追加することによって、グリッドを変更し、例えば:

// add new columns to the data grid 
void AddColumns(string[] newColumnNames) 
{ 
    foreach (string name in newColumnNames) 
    { 
     grid.Columns.Add(new DataGridTextColumn { 
      // bind to a dictionary property 
      Binding = new Binding("Custom[" + name + "]"), 
      Header = name 
     }); 
    } 
} 

あなたがお勧めしますラッパークラスを作成します。ラッパークラスには元のクラスと、カスタムプロパティーを格納する辞書が含まれている必要があります。

void PopulateRows(User[] users, Dictionary<string, object>[] customProps) 
{ 
    var customUsers = users.Select((user, index) => new CustomUser { 
     Custom = customProps[index]; 
    }); 
    grid.ItemsSource = customUsers; 
} 

public class CustomUser : User 
{ 
    public Dictionary<string, object> Custom { get; set; } 

    public CustomUser() : base() 
    { 
     Custom = new Dictionary<string, object>(); 
    } 
} 

は、この新しい「CustomUser」クラスのコレクションをItemsSourceを移入:のはあなたのメインの行クラスは、「ユーザー」であるとしましょう、そしてあなたは、このようなラッパークラスの何かをしたいと思います

したがって、たとえば、それを一緒に結ぶ:

var newColumnNames = new string[] { "Name1", "Name2" }; 
var users = new User[] { new User { id="First User" } }; 
var newProps = new Dictionary<string, object>[] { 
    new Dictionary<string, object> { 
     "Name1", "First Name of First User", 
     "Name2", "Second Name of First User", 
    }, 
}; 
AddColumns(newColumnNames); 
PopulateRows(users, newProps); 

第二アプローチ:DataTableを使用してください。これにより、カスタムタイプのインフラストラクチャがボンネット内で使用されますが、使いやすくなります。ただ、DataGridのItemsSourceDataTable.DefaultViewプロパティをバインド:

Data = new DataTable(); 

// create "fixed" columns 
Data.Columns.Add("id"); 
Data.Columns.Add("image"); 

// create custom columns 
Data.Columns.Add("Name1"); 
Data.Columns.Add("Name2"); 

// add one row as an object array 
Data.Rows.Add(new object[] { 123, "image.png", "Foo", "Bar" }); 

第三のアプローチ:の拡張性のメイク使用あなたが好きしかし

<DataGrid ItemsSource="{Binding Data.DefaultView}" AutoGenerateColumns="True" /> 

その後、あなたは、例えば列を定義することができます.Netのタイプシステム。具体的には、CustomTypeDescriptorを使用します。これにより、実行時にカスタムタイプを作成することができます。これにより、DataGridにタイプが "Name1"、 "Name2"、... "NameN"などのプロパティを持つことを伝えることができます。このアプローチの簡単な例については、hereを参照してください。

+2

DataTableのアプローチが最も簡単で効率的なソリューションであることがわかりました。 –

+0

メソッド3を使用して誰かがDataGridの列を自動生成できましたか?私は既に定義されたカスタム型記述子を持っていますが、そのプロパティにはうまくバインドできますが、列を自動生成することはできません。 – Jesse

+0

同じデータグリッドの値を編集して更新したい場合はどうすればいいですか – Shelly

0

あなたは、単一の大きなデータグリッド(表)の中に、あなたがID、画像、名前、説明とするときレコードの1つは、そのデータグリッドで選択されているとのDataGridを持っている可能性があることを示すために必要とされていない場合ListBoxを表示/更新します。

+0

これは私の問題を解決するものではないと思います。私はレコードを複数の名前を比較する必要がありますいくつかのデータ(邪魔に関係なく)を含む1つの大きなテーブルがあります。したがって、各レコードでは、2人以上の人物を直接比較するために、「N」個のコラムを必要とします。 e。 g。 :レコード1:1; tmp.png; Foo;バー;成功;未処理レコード2:2; tmp2.png; Foo1; bar2;成功しなかった;成功 – Wr4thon

4

第2のアプローチ:DataTableを使用します。これにより、カスタムタイプのインフラストラクチャがボンネット内で使用されますが、使いやすくなります。 DataGridのItemsSourceをDataTable.DefaultViewプロパティにバインドするだけです。

DataTable.DefaultViewプロパティプロパティにバインドするのではなく、ほとんどの場合、DataView型のプロパティを作成してバインドしました。

<DataGrid ItemsSource="{Binding DataView, Mode=TwoWay}" AutoGenerateColumns="True" />

これは、結合は、2つの方法であることができ、DataTable.DefaultViewに結合する結合双方向ことができません。この設定でビューモデルで

public DataView DataView 
    { 
     get { return _dataView; } 
     set 
     { 
      _dataView = value; 
      OnPropertyChanged("DataView"); 
     } 
    } 

ビューモデルが初期化されますが、いつでも動的にデータテーブルを更新し、変更することができたときに私は動的に列を定義することができませんでした。上記のMcGarnagleによって定義されたアプローチを使用すると、DataTableが新しいデータソースで更新されたときにビュースキーマが更新されませんでした。