2009-04-01 65 views
62

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.agregar columnas y filas programáticamente a WPF Datagrid

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

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

Respuesta

65

Para añadir una fila mediante programación:

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

Para agregar una columna mediante programación:

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

Salida this post en el foro de discusión WPF DataGrid para más información.

+4

-1: debido a que muestran la parte dolorosamente fácil, pero no cómo enlazar los datos en realidad a esas columnas en tiempo de ejecución añadido. Estoy seguro de que Andy quiere construir una aplicación que muestre algún tipo de datos, no solo nombres de columnas. – JohnB

+0

Es solo una cuestión de establecer propiedades en DataGridTextColumn. Actualicé la respuesta. –

+0

+1: Confirmé que funciona, gracias. También descubrí que cuando agrega los corchetes, es decir 'Binding (" [FirstName] ")' * vea mi respuesta anterior a continuación *, que funcione, pero es significativamente más lenta al enlazar grandes conjuntos de datos. – JohnB

11

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

Desafortunadamente, con 47 columnas definen de esta manera, que 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 usando 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; 
} 
+0

¿Encontró alguna solución para esto en ese entonces? – 321X

+2

¿Por qué usa "[{0}]" en la ruta de enlace? No funciona para mí, pero cuando uso el nombre sin cuadrado y curlies, ¿funciona? – smerlung

3

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 es o no está en línea con la mayoría directrices, como MVVM)

la opción 1: como JohnB dijo. Pero creo que usted debe utilizar su propia colección definida en lugar de un DataTable tipos débiles (sin ánimo de ofender, pero no se puede decir que desde el código lo que cada columna representa)

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 el tipo tiene una propiedad FirstName definido, 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); 

Esto, obviamente, no funciona si usted no sabe propiedades que se necesitan para mostrar en su dataGrid, pero si ese es el caso, tendrá más problemas para hacer frente, y creo que está fuera de alcance aquí.

4

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


he publicado un proyecto de muestra que describe cómo utilizar delegados PropertyDescriptor y lambda con ObservableCollection dinámico y DynamicObject para rellenar una cuadrícula con definiciones de columnas de tipo fuerte.

Columnas se pueden agregar/eliminar en el tiempo de ejecución dinámicamente. 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; } 

Se pueden 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 mecanografiado (relacionado 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, solo tiene que enlazar a las colecciones de los 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.

+0

hola ... su enlace no funciona –

+0

@doblak Encuentro que esto es exactamente lo que necesito. ¿Todavía tienes el código de tu solución? – zhangz

+0

@zhangz actualizó la respuesta, consulte esta publicación para la idea de DynamicPropertyDescriptor: https://jopinblog.wordpress.com/2007/05/12/dynamic-propertydescriptors-with-anonymous-methods/ – doblak

23

probar esto, que funciona al 100%: agregar columnas y filas programáticamente: necesita crear clase de elemento en un primer momento:

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

     } 
+0

¿Hay alguna forma de agregar encabezado de columna múltiple? usando este código? – Denis

16

que tenían el mismo problema. Agregar nuevas filas a WPF DataGrid requiere un truco. DataGrid se basa en los campos de propiedad de un objeto de elemento. ExpandoObject permite agregar nuevas propiedades dinámicamente. El código siguiente se 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 manera cómo el componente se debe utilizar, sin embargo, se simplifica mucho si sólo se haya generado mediante programación datos (por ejemplo, en mi caso: una secuencia de características y salida de red neuronal).

+1

exactamente lo que estaba buscando. ¡muchas gracias! –

0

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 es o no está en línea con la mayoría de las directrices, como MVVM)

A continuación, sólo se unen a los usuarios colecciones y columnas son generados automáticamente a medida que los speficy. 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.

+0

Por favor, agregue un ejemplo de código a su respuesta – Dethariel

Cuestiones relacionadas