#c# #list #winforms #datatable #datagridview
#c# #Список #winforms #таблица данных #datagridview
Вопрос:
Я нашел get datatable из «выбранных строк», но не смог найти из «выбранных ячеек». Мне нужна помощь для этого.
Чтобы решить эту проблему, я составил два списка из выбранных ячеек. Эти два списка содержат номера индексов столбцов и индексов строк, как вы видите ниже. Есть ли какой-либо способ получить datatable из этих списков? Если нет, не могли бы вы дать мне какие-либо другие решения?
Индекс столбца список индексов строк:
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();
Ответ №1:
Вероятно, здесь не важно знать или различать индексы;
DataGridViewCell
сможет ссылаться на его OwnerColumn
и OwnerRow
, который будет содержать не только Index
свойство, но также информацию о типе и имя.
Я собираюсь предоставить метод расширения ( GetDataTable
), который демонстрирует генерацию DataTable
имени "SelectedCell"
.
Сначала он гарантирует, что столбцы будут добавлены в новый DataTable
экземпляр, поскольку это определит поля, используемые строками. При создании строк в новом DataTable
мы будем условно перебирать исходные cells
(полагаясь на уникальные имена столбцов повсюду) и 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);
}
}
Для тестирования вот фрагмент, в котором я создал Form
и добавил 2 DataGridView
элемента управления.
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);
}
Как вы можете видеть, необходимо учитывать и обрабатывать поведение элементов управления, в том числе:
- выбор, когда элементы управления ячейками находятся в состоянии редактирования.
- сортировка, когда выборки не являются однородными.
- обработка типа столбца ячейки
Комментарии:
1. Спасибо вам и за потраченное время. Я протестировал сейчас. Он отлично работает.