77 votes

Ajouter par programme des colonnes et des lignes à la grille de données WPF.

Je suis novice en matière de WPF. Je veux juste savoir comment ajouter des colonnes et des lignes de manière programmatique à un DataGrid dans WPF. La façon dont nous avions l'habitude de le faire dans les formulaires Windows : créer des colonnes et des lignes de tableau, et les lier à la DataGrid.

Je crois que la grille de données WPF est un peu différente de celle utilisée en ASP.net et Windows form (corrigez-moi si je me trompe).

J'ai un certain nombre de lignes et de colonnes que je dois dessiner dans la grille de données afin que l'utilisateur puisse modifier les données dans les cellules. Faites-moi savoir si vous avez des idées.

76voto

John Myczek Points 6205

Pour ajouter une rangée de manière programmée :

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

Pour ajouter une colonne de manière programmée :

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

Vérifiez ce poste sur le forum de discussion WPF DataGrid pour plus d'informations.

30voto

aminescm Points 121

Essayez ceci, cela fonctionne à 100% : ajoutez des colonnes et des lignes par programme : vous devez d'abord créer une classe d'éléments :

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" });

        }

26voto

J'ai eu le même problème. Ajouter de nouvelles lignes à WPF DataGrid nécessite une astuce. DataGrid s'appuie sur les champs de propriété d'un objet item. ExpandoObject permet d'ajouter de nouvelles propriétés de manière dynamique. Le code ci-dessous explique comment le faire :

// 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);

//edit :

Notez que ce n'est pas la façon dont le composant devrait être utilisé, cependant, il simplifie beaucoup si vous avez seulement des données générées par programme (par exemple, dans mon cas : une séquence de caractéristiques et de sortie de réseau neuronal).

12voto

JohnB Points 6869

J'ai trouvé une solution qui ajoute des colonnes au moment de l'exécution, et qui se lie à un fichier de type DataTable .

Malheureusement, avec 47 colonnes définies de cette manière, la liaison avec les données n'est pas assez rapide pour moi. Avez-vous des suggestions ?

xaml

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

xaml.cs en 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(string.Format("[{0}]", col.ColumnName))
      });
  }

  dataGrid.DataContext = table;
}

5voto

doblak Points 1578

J'ai posté un projet d'exemple décrivant comment utiliser PropertyDescriptor et délégués lambda avec ObservableCollection et DynamicObject dynamiques pour remplir une grille avec fortement typé les définitions des colonnes.

Les colonnes peuvent être ajoutées/supprimées au moment de l'exécution. dynamiquement . Si vos données ne sont pas un objet de type connu, vous pouvez créer une structure de données permettant un accès par un nombre quelconque de colonnes et spécifier un PropertyDescriptor pour chaque "colonne".

Par exemple :

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

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

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) 

Ou encore mieux, dans le cas de certains objets réels

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

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

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);

Il suffit ensuite de lier les collections d'utilisateurs et les colonnes sont générées automatiquement au fur et à mesure que vous les spécifiez. Les chaînes transmises aux descripteurs de propriétés sont les noms des en-têtes de colonnes. Au moment de l'exécution, vous pouvez ajouter d'autres PropertyDescriptors à 'Users' pour ajouter une autre colonne à la grille.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X