Я реализую свой собственный элемент управления на основе Grid
(, а не DataGrid
). Этот элемент управления отображает содержимое DataTable
и поддерживает выбор столбцов, строк и элементов (причина неиспользования DataGrid
заключается в сложности таких манипуляций). Он наполняется такими элементами:
private void DrawGrid(DataTable table)
{
// grdMain stays for the grid itslef
grdMain.RowDefinitions.Clear();
grdMain.ColumnDefinitions.Clear();
var padding = new Thickness(5, 2, 5, 2);
for (int colNumber = 0; colNumber <= table.Columns.Count; colNumber++)
{
//Here comes logic for ColumnDefinitions addition
}
//First row is for table header
grdMain.RowDefinitions.Add(new RowDefinition());
//Main loop where the whole stuff gets added into the table
for (int rowNumber = 1; rowNumber <= table.Rows.Count; rowNumber++)
{
grdMain.RowDefinitions.Add(new RowDefinition());
// First column is for row numbers
for (int colNumber = 1; colNumber <= table.Columns.Count; colNumber++)
{
//grdMain.Children.Add(CreateHeaderTextBlock(rowNumber.ToString(), 0, rowNumber, false));
//grdMain.Children.Add(CreateColumnHeaderRectangle(0, rowNumber));
var cellTextBlock = new TextBlock()
{
Text = table.Rows[rowNumber - 1][colNumber - 1].ToString(),
Padding = padding
};
grdMain.Children.Add(cellTextBlock);
cellTextBlock.SetValue(Grid.RowProperty, rowNumber);
cellTextBlock.SetValue(Grid.ColumnProperty, colNumber);
}
}
}
Код довольно прост, но ему не хватает виртуализации элементов. Для таблицы 1000x10 на рендеринг уходит более 3 секунд, а узким местом является макет.
Есть идеи о том, как реализовать виртуализацию? Сетка grdMain
находится в ScrollViewer
, что позволяет прокручивать эту сетку. Теоретически я мог бы загрузить новые элементы и добавить их при прокрутке, но я не уверен, будут ли полосы прокрутки работать правильно.
UPD: DataTable
, который передается как параметр, ничего, кроме BindableProperty
:
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(DataTable), typeof(TableSelector),
new FrameworkPropertyMetadata(new DataTable(), OnItemsSourceChanged));
public DataTable ItemsSource
{
get => (DataTable)GetValue(ItemsSourceProperty);
set => SetValue(ItemsSourceProperty, value);
}
Обратный вызов OnItemsSourceChanged
вызывает метод DrawGrid
для повторного рендеринга таблицы.