Reputation: 497
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();
Upvotes: 1
Views: 127
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);
}
As you can see, there are control behaviors to consider and handle, including:
Upvotes: 2