GridX Virtualization
Virtual data source and row/column virtualization for handling millions of rows with minimal memory and instant scrolling
Overview
The grid virtualization system enables efficient rendering of arbitrarily large datasets by only materializing rows that are visible in the viewport, plus a configurable overscan buffer:
- IVirtualDataSource — Contract for providing row data on demand
- GridVirtualDataSource — Built-in implementation with preloading and total-count tracking
- GridRowVirtualizer — Manages the visible window and requests data from the source
- GridColumnVirtualizer — Column-level virtualization for wide datasets
IVirtualDataSource
public interface IVirtualDataSource
{
long TotalRowCount { get; }
IEnumerable<VirtualRowData> GetRows(long startIndex, int count);
void PreloadWindow(long startIndex, int visibleCount, int overscan);
void SetTotalRowCount(long count);
event EventHandler? TotalRowCountChanged;
}
// Built-in implementations:
var source = GridVirtualDataSource.FromList(myList);
var source = GridVirtualDataSource.FromDataTable(myTable);
var source = GridVirtualDataSource.FromAsync(fetchCallback);GridRowVirtualizer
var virtualizer = new GridRowVirtualizer(grid);
virtualizer.DataSource = myVirtualSource;
// Internal window management:
// visibleWindow: first visible row + visible row count
// overscanWindow: visibleWindow + padding above/below
// rowCache: Dictionary<long, VirtualRowData> for current windowPreloading Strategy
- Visible window — Rows currently visible in the grid viewport
- Overscan buffer — Extra rows above and below the visible window (default: 2x visible count)
- Preloading — DataSource.PreloadWindow() is called on scroll to hint future data needs
- Cache invalidation — Cache is invalidated when scrolling beyond buffer or when TotalRowCount changes
Examples
// Virtual grid with 10 million rows
var source = new GridVirtualDataSource();
source.SetTotalRowCount(10_000_000);
grid.RowVirtualizer.DataSource = source;
// Custom async data source
public class DatabaseDataSource : IVirtualDataSource
{
public long TotalRowCount => db.Count<Customer>();
public IEnumerable<VirtualRowData> GetRows(
long startIndex, int count)
{
return db.Customers.Skip((int)startIndex).Take(count)
.Select(c => VirtualRowData.FromObject(c));
}
}