Ajouter par programme une colonne et des lignes à la grid de données WPF

Je suis nouveau sur WPF. Je veux juste savoir comment append des colonnes et des lignes par programmation à un DataGrid dans WPF. La façon dont nous le faisions dans les formulaires Windows. créer des colonnes et des lignes de table et le lier à DataGrid.

Je pense que WPF DataGrid est légèrement différent de celui utilisé dans ASP.net et Windows (corrigez-moi si je me trompe).

J’ai un nombre de lignes et de colonnes que je dois dessiner dans DataGrid pour que l’utilisateur puisse éditer les données dans les cellules.

Ajouter par programme une ligne:

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

Pour append une colonne par programmation:

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

Consultez ce post sur le forum de discussion WPF DataGrid pour plus d’informations.

Essayez ceci, cela fonctionne 100%: ajoutez des colonnes et des lignes par programmation: vous devez d’abord créer une classe d’élément:

 public class Item { public int Num { get; set; } public ssortingng Start { get; set; } public ssortingng 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" }); } 

J’ai eu le même problème. L’ajout de nouvelles lignes à WPF DataGrid nécessite une astuce. DataGrid repose sur les champs de propriété d’un object d’élément. ExpandoObject permet d’append de nouvelles propriétés de manière dynamic. Le code ci-dessous explique comment le faire:

 // using System.Dynamic; DataGrid dataGrid; ssortingng[] labels = new ssortingng[] { "Column 0", "Column 1", "Column 2" }; foreach (ssortingng 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)row)[labels[i].Replace(' ', '_')] = values[i]; dataGrid.Items.Add(row); 

//modifier:

Notez que ce n’est pas ainsi que le composant doit être utilisé, cependant, cela simplifie beaucoup si vous ne disposez que de données générées par programme (par exemple, dans mon cas: une séquence de fonctionnalités et une sortie de réseau neuronal).

J’ai trouvé une solution qui ajoute des colonnes à l’exécution et se lie à un DataTable .

  • Comment associer un DataGrid WPF à un nombre variable de colonnes?

Malheureusement, avec 47 colonnes définies de cette manière, cela ne lie pas assez rapidement les données pour moi. Aucune suggestion?

xaml

   

xaml.cs utilisant System.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(ssortingng.Format("[{0}]", col.ColumnName)) }); } dataGrid.DataContext = table; } 

edit : désolé, je n’ai plus le code mentionné ci-dessous. C’était une solution soignée, bien que complexe.


J’ai posté un exemple de projet décrivant comment utiliser PropertyDescriptor et les delegates lambda avec des ObservableCollection dynamics et DynamicObject pour remplir une grid avec des définitions de colonnes fortement typées .

Les colonnes peuvent être ajoutées / supprimées lors de l’exécution de manière dynamic . Si vos données ne sont pas un object de type connu, vous pouvez créer une structure de données permettant d’accéder à un nombre illimité de colonnes et spécifiant un PropertyDescriptor pour chaque “colonne”.

Par exemple:

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

Vous pouvez définir des colonnes de cette manière:

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

Ou même mieux, dans le cas de certains objects réels

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

Vous pouvez spécifier des colonnes fortement typées (liées à votre modèle de données):

 var propertyDescriptors = new List { new DynamicPropertyDescriptor("First name", x => x.FirstName ), new DynamicPropertyDescriptor("Last name", x => x.LastName ), ... } var users = resortingeve some users Users = new DynamicDataGridSource(users, propertyDescriptors, PropertyChangedListeningMode.Handler); 

Ensuite, il suffit de lier les collections des utilisateurs et les colonnes sont générées automatiquement lorsque vous les définissez. Les chaînes transmises aux descripteurs de propriétés sont des noms pour les en-têtes de colonne. Au moment de l’exécution, vous pouvez append d’autres PropertyDescriptors à «Utilisateurs» pour append une autre colonne à la grid.

Si vous avez déjà la liaison de données en place, la réponse de John Myczek est complète.
Sinon, vous avez au moins 2 options que je connais si vous souhaitez spécifier la source de vos données. (Cependant, je ne suis pas sûr que cela soit conforme ou non à la plupart des directives, comme MVVM)

option 1: comme l’a dit JohnB. Mais je pense que vous devriez utiliser votre propre collection définie au lieu d’un DataTable faiblement typé (pas de délit, mais vous ne pouvez pas dire à partir du code ce que chaque colonne représente)

xaml.cs

 DataContext = myCollection; //myCollection is a `ICollection` preferably `ObservableCollection - option 2) Declare the name of the Datagrid in xaml  

dans xaml.cs

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

Si votre type a une propriété FirstName définie, vous pouvez alors faire ce que John Myczek a souligné.

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

Cela ne fonctionne évidemment pas si vous ne connaissez pas les propriétés que vous devrez afficher dans votre grid de données, mais si tel est le cas, vous aurez plus de problèmes à gérer, et je pense que cela est hors de propos ici.

Si vous avez déjà la liaison de données en place, la réponse de John Myczek est complète. Sinon, vous avez au moins deux options que je connais si vous souhaitez spécifier la source de vos données. (Cependant, je ne suis pas sûr que cela soit conforme ou non à la plupart des directives, comme MVVM)

Ensuite, il suffit de lier les collections des utilisateurs et les colonnes sont générées automatiquement lorsque vous les définissez. Les chaînes transmises aux descripteurs de propriétés sont des noms pour les en-têtes de colonne. Au moment de l’exécution, vous pouvez append d’autres PropertyDescriptors à «Utilisateurs» pour append une autre colonne à la grid.