web-dev-qa-db-fra.com

Comment construire un DataTable à partir d'un DataGridView?

Je regarde peut-être ce problème à l'envers, mais je suis quand même curieux. Existe-t-il un moyen de construire un DataTable à partir de ce qui est actuellement affiché dans le DataGridView?

Pour être clair, je sais que vous pouvez faire cela DataTable data = (DataTable)(dgvMyMembers.DataSource); mais cela inclut des colonnes cachées. Je voudrais le construire à partir des colonnes affichées uniquement.

J'espère que cela a du sens.


J'ai donc fini par essayer une combinaison de quelques réponses comme cela me semblait le mieux. Voici ce que j'essaie. Fondamentalement, je crée le DataTable à partir du DataSource, puis je travaille en arrière en fonction du fait qu'une colonne soit visible ou non. Cependant, après avoir supprimé une colonne, j'obtiens un Collection was modified; enumeration operation may not execute à la prochaine itération de foreach.

Je suis confus car je ne suis pas essayant de modifier le DataGridView, seulement le DataTable alors, quoi de neuf?

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;
    }
14

Eh bien, vous pouvez le faire

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

puis utiliser

data.Columns.Remove(...);

Je pense que c'est le moyen le plus rapide. Cela modifiera la table de source de données, si vous ne le souhaitez pas, alors une copie de la table est requise. Sachez également que DataGridView.DataSource n'est pas nécessairement de type DataTable.

20
Petr Abdulin

Je ne sais rien de ce qui est fourni par le Framework (au-delà de ce que vous voulez éviter) qui ferait ce que vous voulez mais (comme je le pense, vous le savez), il serait assez facile de créer quelque chose de simple vous-même:

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;
}
16
Jay Riggs

une des meilleures solutions a bien plu;)

  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; }
        }
6

Convertissez d'abord les données de datagridview en List, puis convertissez List en DataTable

        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;
    }
3
xling