私はWPFが初めてです。WPF の DataGrid に列と行をプログラムで追加する方法を知りたいだけです。Windows フォームで行っていた方法です。テーブルの列と行を作成し、DataGrid にバインドします。
WPF DataGrid は、ASP.net および Windows フォームで使用されているものとは少し異なると思います (間違っている場合は修正してください)。
ユーザーがセル内のデータを編集できるように、DataGrid に描画する必要がある行と列の数があります。
私はWPFが初めてです。WPF の DataGrid に列と行をプログラムで追加する方法を知りたいだけです。Windows フォームで行っていた方法です。テーブルの列と行を作成し、DataGrid にバインドします。
WPF DataGrid は、ASP.net および Windows フォームで使用されているものとは少し異なると思います (間違っている場合は修正してください)。
ユーザーがセル内のデータを編集できるように、DataGrid に描画する必要がある行と列の数があります。
プログラムで行を追加するには:
DataGrid.Items.Add(new DataItem());
プログラムで列を追加するには:
DataGridTextColumn textColumn = new DataGridTextColumn();
textColumn.Header = "First Name";
textColumn.Binding = new Binding("FirstName");
dataGrid.Columns.Add(textColumn);
詳細については、WPFDataGridディスカッション掲示板のこの投稿を確認してください。
これを試してください、それは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" });
}
私も同じ問題を抱えていました。WPF に新しい行を追加するにDataGrid
は、コツが必要です。DataGrid
item オブジェクトのプロパティ フィールドに依存します。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);
//編集:
これはコンポーネントの使用方法ではないことに注意してください。ただし、プログラムで生成されたデータ (たとえば、一連の機能とニューラル ネットワークの出力) しかない場合は、大幅に簡素化されます。
実行時に列を追加し、にバインドするソリューションを見つけましたDataTable
。
残念ながら、このように定義された 47 列では、十分な速さでデータにバインドできません。助言がありますか?
xaml
<DataGrid
Name="dataGrid"
AutoGenerateColumns="False"
ItemsSource="{Binding}">
</DataGrid>
System.Windows.Data を使用するxaml.cs ;
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;
}
編集:申し訳ありませんが、私はもう以下のコードを持っていません。複雑ではありますが、それはきちんとした解決策でした。
PropertyDescriptorとラムダデリゲートを動的ObservableCollectionとDynamicObjectで使用して、強く型付けされた列定義をグリッドに設定する方法を説明するサンプルプロジェクトを投稿しました。
列は実行時に動的に追加/削除できます。データが既知のタイプのオブジェクトでない場合は、任意の数の列によるアクセスを可能にするデータ構造を作成し、各「列」に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を追加して、グリッドに別の列を追加できます。
すでにデータバインディングを設定している場合は、JohnMyczekの回答が完了しています。
そうでない場合は、データのソースを指定するかどうかを私が知っている少なくとも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}>
xaml.csで
CollectionView myCollectionView =
(CollectionView)CollectionViewSource.GetDefaultView(yourCollection);
dataGrid.ItemsSource = myCollectionView;
タイプにFirstNameプロパティが定義されている場合は、JohnMyczekが指摘したことを実行できます。
DataGridTextColumn textColumn = new DataGridTextColumn();
dataColumn.Header = "First Name";
dataColumn.Binding = new Binding("FirstName");
dataGrid.Columns.Add(textColumn);
dataGridに表示する必要のあるプロパティがわからない場合、これは明らかに機能しませんが、その場合は、対処する必要のある問題がさらに増えることになります。これは、ここでは範囲外だと思います。
データバインディングが既に整っている場合、John Myczek の回答は完了です。そうでない場合は、データのソースを指定したい場合、私が知っている少なくとも 2 つのオプションがあります。(ただし、これがMVVMなどのほとんどのガイドラインに沿っているかどうかはわかりません)
次に、Users コレクションにバインドするだけで、列を指定すると列が自動生成されます。プロパティ記述子に渡される文字列は、列ヘッダーの名前です。実行時に、さらに PropertyDescriptor を「ユーザー」に追加して、別の列をグリッドに追加できます。