web-dev-qa-db-ja.com

プログラムで列と行をWPF Datagridに追加

私はWPFが初めてです。 WPFでDataGridにプログラムで列と行を追加する方法を知りたいだけです。 Windowsフォームでの使用方法。テーブルの列と行を作成し、DataGridにバインドします。

WPF DataGridは、ASP.netおよびWindowsフォームで使用されているものとは少し異なると思います(間違っている場合は修正してください)。

ユーザーがセル内のデータを編集できるように、DataGridで描画する必要がある行と列の数があります。

67
Andy

プログラムで行を追加するには:

DataGrid.Items.Add(new DataItem());

プログラムで列を追加するには:

DataGridTextColumn textColumn = new DataGridTextColumn(); 
textColumn.Header = "First Name"; 
textColumn.Binding = new Binding("FirstName"); 
dataGrid.Columns.Add(textColumn); 

詳細については、WPF DataGridディスカッションボードの この投稿 をご覧ください。

69
John Myczek

これを試してください、それは100%動作します:プログラムで列と行を追加します:最初にアイテムクラスを作成する必要があります:

public class Item
        {
            public int Num { get; set; }
            public string Start { get; set; }
            public string Finich { get; set; }
        }

        private void generate_columns()
        {
            DataGridTextColumn c1 = new DataGridTextColumn();
            c1.Header = "Num";
            c1.Binding = new Binding("Num");
            c1.Width = 110;
            dataGrid1.Columns.Add(c1);
            DataGridTextColumn c2 = new DataGridTextColumn();
            c2.Header = "Start";
            c2.Width = 110;
            c2.Binding = new Binding("Start");
            dataGrid1.Columns.Add(c2);
            DataGridTextColumn c3 = new DataGridTextColumn();
            c3.Header = "Finich";
            c3.Width = 110;
            c3.Binding = new Binding("Finich");
            dataGrid1.Columns.Add(c3);

            dataGrid1.Items.Add(new Item() { Num = 1, Start = "2012, 8, 15", Finich = "2012, 9, 15" });
            dataGrid1.Items.Add(new Item() { Num = 2, Start = "2012, 12, 15", Finich = "2013, 2, 1" });
            dataGrid1.Items.Add(new Item() { Num = 3, Start = "2012, 8, 1", Finich = "2012, 11, 15" });

        }
27
aminescm

同じ問題がありました。 WPF DataGridに新しい行を追加するには、トリックが必要です。 DataGridは、アイテムオブジェクトのプロパティフィールドに依存します。 ExpandoObjectは、新しいプロパティを動的に追加できるようにします。以下のコードはその方法を説明しています。

// using System.Dynamic;

DataGrid dataGrid;

string[] labels = new string[] { "Column 0", "Column 1", "Column 2" };

foreach (string label in labels)
{
    DataGridTextColumn column = new DataGridTextColumn();
    column.Header = label;
    column.Binding = new Binding(label.Replace(' ', '_'));

    dataGrid.Columns.Add(column);
}

int[] values = new int[] { 0, 1, 2 };

dynamic row = new ExpandoObject();

for (int i = 0; i < labels.Length; i++)
    ((IDictionary<String, Object>)row)[labels[i].Replace(' ', '_')] = values[i];

dataGrid.Items.Add(row);

//編集:

これはコンポーネントの使用方法ではないことに注意してください。ただし、プログラムで生成されたデータ(たとえば、私の場合:一連の機能とニューラルネットワーク出力)がある場合は、大幅に簡素化されます。

20

実行時に列を追加し、DataTableにバインドするソリューションを見つけました。

残念ながら、この方法で47列が定義されているため、データに十分な速度でバインドできません。助言がありますか?

xaml

<DataGrid
  Name="dataGrid"
  AutoGenerateColumns="False"
  ItemsSource="{Binding}">
</DataGrid>

xaml.csSystem.Windows.Dataを使用して;

if (table != null) // table is a DataTable
{
  foreach (DataColumn col in table.Columns)
  {
    dataGrid.Columns.Add(
      new DataGridTextColumn
      {
        Header = col.ColumnName,
        Binding = new Binding(string.Format("[{0}]", col.ColumnName))
      });
  }

  dataGrid.DataContext = table;
}
11
JohnB

編集:申し訳ありませんが、以下のコードはもうありません。複雑ではありますが、きちんとしたソリューションでした。


PropertyDescriptorとラムダデリゲートを動的ObservableCollectionとDynamicObjectと共に使用して、グリッドにstrongly-typed列定義を設定する方法を説明するサンプルプロジェクトを投稿しました。

実行時に列を追加/削除できます動的に。データが既知のタイプのオブジェクトでない場合、任意の数の列によるアクセスを可能にするデータ構造を作成し、各「列」にPropertyDescriptorを指定できます。

例えば:

IList<string> ColumnNames { get; set; }
//dict.key is column name, dict.value is value
Dictionary<string, string> Rows { get; set; }

この方法で列を定義できます。

var descriptors= new List<PropertyDescriptor>();
//retrieve column name from preprepared list or retrieve from one of the items in dictionary
foreach(var columnName in ColumnNames)
    descriptors.Add(new DynamicPropertyDescriptor<Dictionary, string>(ColumnName, x => x[columnName]))
MyItemsCollection = new DynamicDataGridSource(Rows, descriptors) 

またはさらに良い、いくつかの実際のオブジェクトの場合

public class User 
{
    public string FirstName { get; set; }
    public string LastName{ get; set; }
    ...
}

厳密に型指定された列(データモデルに関連する)を指定できます。

var propertyDescriptors = new List<PropertyDescriptor>
{
    new DynamicPropertyDescriptor<User, string>("First name", x => x.FirstName ),
    new DynamicPropertyDescriptor<User, string>("Last name", x => x.LastName ),
    ...
}

var users = retrieve some users

Users = new DynamicDataGridSource<User>(users, propertyDescriptors, PropertyChangedListeningMode.Handler);

次に、Usersコレクションにバインドするだけで、列を指定すると自動生成されます。プロパティ記述子に渡される文字列は、列ヘッダーの名前です。実行時に、「ユーザー」に別のPropertyDescriptorsを追加して、グリッドに別の列を追加できます。

4
doblak

既にデータバインディングを配置している場合、John Myczekの回答は完了です。
少なくとも2つのオプションがない場合、データのソースを指定するかどうかを知っています。 (ただし、これがMVVMなどのほとんどのガイドラインに沿っているかどうかはわかりません)

オプション1: JohnBが言ったように。ただし、弱い型指定のDataTableではなく、独自の定義済みコレクションを使用する必要があると思います(違反はありませんが、各列が何を表しているかをコードから知ることはできません)

xaml.cs

DataContext = myCollection;

//myCollection is a `ICollection<YourType>` preferably
`ObservableCollection<YourType>

 - option 2) Declare the name of the Datagrid in xaml

        <WpfToolkit:DataGrid Name=dataGrid}>

in xaml.cs

CollectionView myCollectionView = 
      (CollectionView)CollectionViewSource.GetDefaultView(yourCollection);
dataGrid.ItemsSource = myCollectionView;

タイプにプロパティFirstNameが定義されている場合、John Myczekが指摘したことを実行できます。

DataGridTextColumn textColumn = new DataGridTextColumn(); 
dataColumn.Header = "First Name"; 
dataColumn.Binding = new Binding("FirstName"); 
dataGrid.Columns.Add(textColumn); 

DataGridに表示する必要のあるプロパティがわからない場合、これは明らかに機能しませんが、その場合は対処する必要がある問題が多くなるため、ここでは範囲外と考えています。

3
HCP