c# - una - como agregar filas y columnas a un datagridview
agregar columnas y filas programáticamente a WPF Datagrid (7)
Encontré una solución que agrega columnas en tiempo de ejecución y se une a una DataTable
.
Desafortunadamente, con 47 columnas definidas de esta manera, no se une a los datos lo suficientemente rápido para mí. ¿Alguna sugerencia?
xaml
<DataGrid
Name="dataGrid"
AutoGenerateColumns="False"
ItemsSource="{Binding}">
</DataGrid>
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;
}
Soy nuevo en WPF. Solo quiero saber cómo debemos agregar columnas y filas mediante programació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.
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. 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<YourType>` preferably
`ObservableCollection<YourType>
- option 2) Declare the name of the Datagrid in xaml
<WpfToolkit:DataGrid Name=dataGrid}>
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 alcance aquí.
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<String, Object>)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 programación (por ejemplo, en mi caso: una secuencia de características y salida de red neuronal).
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" });
}
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 delegados 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<string> ColumnNames { get; set; }
//dict.key is column name, dict.value is value
Dictionary<string, string> Rows { get; set; }
Puede definir columnas de esta manera:
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)
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<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);
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.