2011-06-09 23 views
8

Bien puedo estar mirando este problema al revés, pero tengo curiosidad, no obstante. ¿Hay alguna forma de crear un DataTable a partir de lo que se muestra actualmente en el DataGridView?¿Cómo construir una DataTable desde un DataGridView?

Para ser claros, sé que puede hacer esto DataTable data = (DataTable)(dgvMyMembers.DataSource);, pero eso incluye columnas ocultas. Me gustaría construirlo solo a partir de las columnas mostradas.

Espero que tenga sentido.


Así que terminé tratando una combinación de un par de respuestas, ya que parecía lo mejor. Debajo está lo que estoy intentando. Básicamente estoy creando la DataTable de DataSource y luego trabajando hacia atrás en función de si una columna está visible o no. Sin embargo, después de eliminar una columna obtengo un Collection was modified; enumeration operation may not execute en la próxima iteración del foreach.

Estoy confundido ya que no soy tratando para modificar el DataGridView, sólo el DataTable ¿y qué pasa?

DataTable data = GetDataTableFromDGV(dgvMyMembers); 


    private DataTable GetDataTableFromDGV(DataGridView dgv) 
    { 
     var dt = ((DataTable)dgv.DataSource).Copy(); 
     foreach (DataGridViewColumn column in dgv.Columns) 
     { 
      if (!column.Visible) 
      { 
       dt.Columns.Remove(column.Name); 
      } 
     } 
     return dt; 
    } 
+1

Recibirá el error porque DataTable está vinculado a la DGV; cuando elimina la columna del DT, también se elimina la columna encuadernada del DGV. Haga una copia del DT antes de eliminar columnas, cambie su asignación a 'dt' a:' var dt = ((DataTable) dgv.DataSource). Copia(); ' –

+0

Eso lo hizo, gracias –

Respuesta

14

Bueno, puede hacerlo

DataTable data = (DataTable)(dgvMyMembers.DataSource); 

y luego usar

data.Columns.Remove(...); 

Creo que es la manera más rápida. Esto modificará la tabla de fuente de datos, si no la quiere, entonces se requiere una copia de la tabla. También tenga en cuenta que DataGridView.DataSource no es necesariamente del tipo DataTable.

+2

¡Buena respuesta! Agradezco el código conciso. También le doy crédito por usar Gadget como su avatar. ¡La vieja escuela para ganar! –

+0

No estoy seguro a quién dar la marca de verificación en esto. Mi solución terminó siendo una combinación igual de esta respuesta y respuesta de Jay Riggs. –

13

No sé nada proporcionado por el marco (más allá de lo que se quiere evitar) que haga lo que quiera, pero (como sospecho que sabes) que sería muy fácil crear algo simple sí mismo:

private DataTable GetDataTableFromDGV(DataGridView dgv) { 
    var dt = new DataTable(); 
    foreach (DataGridViewColumn column in dgv.Columns) { 
     if (column.Visible) { 
      // You could potentially name the column based on the DGV column name (beware of dupes) 
      // or assign a type based on the data type of the data bound to this DGV column. 
      dt.Columns.Add(); 
     } 
    } 

    object[] cellValues = new object[dgv.Columns.Count]; 
    foreach (DataGridViewRow row in dgv.Rows) { 
     for (int i = 0; i < row.Cells.Count; i++) { 
      cellValues[i] = row.Cells[i].Value; 
     } 
     dt.Rows.Add(cellValues); 
    } 

    return dt; 
} 
+0

Impresionante, me quedé atascado pero me da la mejor respuesta. !!! – LuckyS

2

en primer lugar, convertir los datos de DataGridView a la lista, a continuación, convertir a DataTable Lista

 public static DataTable ToDataTable<T>(this List<T> list) where T : class { 
     Type type = typeof(T); 
     var ps = type.GetProperties (); 
     var cols = from p in ps 
        select new DataColumn (p.Name , p.PropertyType); 

     DataTable dt = new DataTable(); 
     dt.Columns.AddRange(cols.ToArray()); 

     list.ForEach ((l) => { 
      List<object> objs = new List<object>(); 
      objs.AddRange (ps.Select (p => p.GetValue (l , null))); 
      dt.Rows.Add (objs.ToArray ()); 
     }); 

     return dt; 
    } 
6

uno de mejor solución disfrutó;)

public DataTable GetContentAsDataTable(bool IgnoreHideColumns=false) 
     { 
      try 
      { 
       if (dgv.ColumnCount == 0) return null; 
       DataTable dtSource = new DataTable(); 
       foreach (DataGridViewColumn col in dgv.Columns) 
       { 
        if (IgnoreHideColumns & !col.Visible) continue; 
        if (col.Name == string.Empty) continue; 
        dtSource.Columns.Add(col.Name, col.ValueType); 
        dtSource.Columns[col.Name].Caption = col.HeaderText; 
       } 
       if (dtSource.Columns.Count == 0) return null; 
       foreach (DataGridViewRow row in dgv.Rows) 
       { 
        DataRow drNewRow = dtSource.NewRow(); 
        foreach (DataColumn col in dtSource .Columns) 
        { 
         drNewRow[col.ColumnName] = row.Cells[col.ColumnName].Value; 
        } 
        dtSource.Rows.Add(drNewRow); 
       } 
       return dtSource; 
      } 
      catch { return null; } 
     } 
+0

La excepción se produce en dtSource.Columns.Add (col.Name, col.ValueType); comando si ValueType == null –

Cuestiones relacionadas