Gokhan
Gokhan

Reputation: 497

Make a datatable from DataGridViewSelected Cells c#

I found get datatable from "selected rows" but i couldn't find from "selected cells". I need help for it.

To solve it, i made two lists from selected cells. These two lists contain column index and row index numbers as you see below. Is there any way to get datatable from these lists? If not, could you give me any other solutions?

Column index an Row index list:

 List<int> cols = dgv.SelectedCells.Cast<DataGridViewCell>().Select(x => x.ColumnIndex).Distinct().ToList();
 List<int> rows = dgv.SelectedCells.Cast<DataGridViewCell>().Select(x => x.RowIndex).Distinct().ToList();

enter image description here

Upvotes: 1

Views: 127

Answers (1)

Brett Caswell
Brett Caswell

Reputation: 1504

It probably isn't important to know or distinguish on indexes here;

DataGridViewCell will be able to reference to\of it's OwnerColumn and OwnerRow, which will contain not only Index property but also type information and name.

I'm going to provide an extension method (GetDataTable) that demonstrates generating a DataTable named "SelectedCell".

It will first ensure Columns are added to a new DataTable instance, as that will define the fields used by the rows. While creating rows on the new DataTable, we'll conditionally iterate over the initial cells (relying on unique column naming throughout) and SetField.

public static class DataGridViewExtension
{

    public static DataTable GetDataTable(this DataGridViewSelectedCellCollection cellCollection)
    {
        var cells = cellCollection.Cast<DataGridViewCell>()
            .OrderBy(item => item.RowIndex)
            .ThenBy(item => item.ColumnIndex);

        var cellTuples = cells.Select(c => (c.OwningRow, c.OwningColumn, c.Value)).ToArray();
        var distinctColumns = cellTuples.Select(c => c.OwningColumn).Distinct();
        var distinctRows = cellTuples.Select(c => c.OwningRow).Distinct();

        var dt = new DataTable("SelectedCell");

        foreach (var col in distinctColumns)
        {
            // if selected cells are jagged, we may have to add support for, or specify, nullable types of column value type.
            dt.Columns.Add(col.Name, col.ValueType ?? typeof(object));
        }

        foreach (var row in distinctRows)
        {
            var newRow = dt.NewRow();                
            foreach (var (_, OwningColumn, Value) in cellTuples.Where(item => item.OwningRow == row))
            {
                newRow.SetField(OwningColumn.Name, Value);
            }
            dt.Rows.Add(newRow);
        }

        return dt;
    }

    public static IDataReader GetDataReader(this DataGridViewSelectedCellCollection collection)
    {
        var dt = collection.GetDataTable();           
        return new DataTableReader(dt);
    }
}

To Test, here is a snippet where I created Form and Added 2 DataGridView controls.

public Form1()
{
    dataGridView1.SelectionChanged += DataGridView1_SelectionChanged;
}

private void DataGridView1_SelectionChanged(object sender, EventArgs e)
{
    var dt = dataGridView1.SelectedCells.GetDataTable();
    dataGridView2.ClearSelection();
    dataGridView2.DataSource = null;
    dataGridView2.DataSource = dt;
    //var dataReader = dataGridView1.SelectedCells.GetDataReader();
    //var odt = new DataTable("OtherSelectedCells");
    //odt.Load(dataReader);
}

Snippet of Form with DataGridView

As you can see, there are control behaviors to consider and handle, including:

  • selecting while cell controls are in edit state.
  • sorting when selections are not uniform.
  • column\cell type handling

Upvotes: 2

Related Questions