agregar columnas y filas programáticamente a WPF Datagrid

Soy nuevo en WPF. Solo quiero saber cómo debemos agregar columnas y filas mediante progtwigción a un DataGrid en WPF. La forma en que solíamos hacerlo en formularios de Windows. crear columnas y filas de tabla, y vincularlo a DataGrid.

Creo que WPF DataGrid es un poco diferente al utilizado en ASP.net y Windows (corrígeme si estoy equivocado).

Tengo el número de filas y columnas que necesito dibujar en DataGrid para que el usuario pueda editar los datos en las celdas.

Para agregar programáticamente una fila:

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

Para agregar programáticamente una columna:

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

Echa un vistazo a esta publicación en el foro de discusión de WGF DataGrid para más información.

intente esto, funciona al 100%: agregue columnas y filas programáticamente: primero debe crear una clase de elemento:

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

Yo tuve el mismo problema. Agregar nuevas filas a WPF DataGrid requiere un truco. DataGrid basa en los campos de propiedad de un objeto de elemento. ExpandoObject permite agregar nuevas propiedades dinámicamente. El siguiente código explica cómo hacerlo:

 // 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)row)[labels[i].Replace(' ', '_')] = values[i]; dataGrid.Items.Add(row); 

//editar:

Tenga en cuenta que esta no es la forma en que se debe utilizar el componente, sin embargo, simplifica mucho si solo ha generado datos generados mediante progtwigción (por ejemplo, en mi caso: una secuencia de características y salida de neural network).

Encontré una solución que agrega columnas en tiempo de ejecución y se une a una DataTable .

  • ¿Cómo puedo vincular un WGD DataGrid con un número variable de columnas?

Desafortunadamente, con 47 columnas definidas de esta manera, no se une a los datos lo suficientemente rápido para mí. ¿Alguna sugerencia?

xaml

   

xaml.cs utilizando 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; } 

editar : lo siento, ya no tengo el código mencionado a continuación. Fue una solución ordenada, aunque compleja.


Publiqué un proyecto de ejemplo que describe cómo usar PropertyDescriptor y delegates lambda con Dynamic ObservableCollection y DynamicObject para rellenar una grilla con definiciones de columna fuertemente tipadas .

Las columnas se pueden agregar / eliminar en el tiempo de ejecución de forma dinámica . Si sus datos no son un objeto con un tipo conocido, puede crear una estructura de datos que permita el acceso por cualquier cantidad de columnas y especificar un PropertyDescriptor para cada “columna”.

Por ejemplo:

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

Puede definir columnas de esta manera:

 var descriptors= new List(); //retrieve column name from preprepared list or retrieve 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) 

O mejor aún, en el caso de algunos objetos reales

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

Puede especificar columnas fuertemente tipadas (relacionadas con su modelo de datos):

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

Luego, simplemente se vincula a las colecciones de usuarios y las columnas se generan automáticamente a medida que las especifique. Las cadenas pasadas a los descriptores de propiedad son nombres para encabezados de columna. En tiempo de ejecución puede agregar más PropertyDescriptors a ‘Users’ agregue otra columna a la grilla.

Si ya tiene el enlace de datos en su lugar, la respuesta de John Myczek está completa.
Si no, tiene al menos 2 opciones que conozco si desea especificar el origen de sus datos. (Sin embargo, no estoy seguro de si esto está en línea con la mayoría de las pautas, como MVVM)

opción 1: como dijo JohnB. Pero creo que debería usar su propia colección definida en lugar de una DataTable débilmente tipada (sin ofender, pero no puede distinguir del código lo que representa cada columna)

xaml.cs

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

en xaml.cs

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

Si su tipo tiene una propiedad FirstName definida, puede hacer lo que señaló John Myczek.

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

Obviamente, esto no funciona si no conoce las propiedades que necesitará mostrar en su grilla de datos, pero si ese es el caso, tendrá más problemas con los que lidiar, y creo que eso está fuera del scope aquí.

Si ya tiene el enlace de datos en su lugar, la respuesta de John Myczek está completa. Si no, tiene al menos 2 opciones que conozco si desea especificar el origen de sus datos. (Sin embargo, no estoy seguro de si esto está en línea con la mayoría de las pautas, como MVVM)

Luego, simplemente se vincula a las colecciones de usuarios y las columnas se generan automáticamente a medida que las especifique. Las cadenas pasadas a los descriptores de propiedad son nombres para encabezados de columna. En tiempo de ejecución puede agregar más PropertyDescriptors a ‘Users’ agregue otra columna a la grilla.