Skip to main content

The Virtual Data Pattern

TeeGrid’s TVirtualData class implements a virtual data pattern that decouples the grid’s rendering engine from the underlying data source. This design provides several key benefits:

Data Source Flexibility

Support any data source by implementing a single interface

Lazy Loading

Retrieve only visible cells on-demand for optimal performance

Large Datasets

Handle millions of rows without loading all data into memory

Framework Agnostic

Same data adapter works across VCL, FMX, and Lazarus

How Virtual Data Works

The virtual data pattern operates on a simple principle: the grid never holds the actual data.

Key Characteristics

1

On-Demand Retrieval

Values are fetched only when needed for display, not preloaded into memory.
2

No Data Duplication

The grid holds no copy of your data - it queries the virtual data adapter each time.
3

Efficient Updates

When data changes, notify the grid via events rather than transferring data.
4

Streaming Support

Data sources without a known row count work perfectly (return -1 from Count()).

TVirtualData Abstract Class

Defined in Tee.GridData.pas, this class establishes the contract for all data adapters:

Required Methods

Every TVirtualData implementation must provide:
Integer
Returns the total number of rows. Return -1 if unknown (streaming data).
String
Retrieves the display value for a specific cell. This is the most performance-critical method.
procedure
Populates the columns collection based on the data structure.
procedure
Associates manually-defined columns with data source fields.
procedure
Updates a cell value when the user edits it.
Single
Calculates the optimal width for a column based on its content.

Optional Override Methods

Returns numeric values for calculations and sorting. Default implementation converts AsString result.
Calculates custom row height. Return True if implemented, False to use default height.
Indicates whether a row can be expanded to show detail data.
Returns a TVirtualData instance for detail rows in master-detail scenarios.
Returns True if the column supports sorting.
Implements sorting logic for the specified column.
Returns current sort state for a column.
Returns True if the column is read-only. Default returns False.
Returns type information for better formatting and editing.

Built-in Implementations

TeeGrid provides three production-ready TVirtualData implementations:

TVirtualDBData (Tee.GridData.DB)

Connects to TDataSet and TDataSource components. Key Features:
  • Automatic field-to-column mapping
  • Full edit support with Post/Cancel
  • Native data type handling
  • Bookmark-based navigation
  • Master-detail relationships
  • Fetch mode configuration (All, Partial, Automatic)
Internal Architecture:
Data Retrieval:

TVirtualData<T> (Tee.GridData.Rtti)

Generic adapter using RTTI for arrays, lists, and objects. Supported Types:
  • TArray<T> - Static arrays
  • TList<T> - Generic lists
  • TObjectList<T> - Object lists
  • Single records/objects
  • 2D arrays (TArray<TArray<T>>)
RTTI-Based Column Creation:
Value Access:
Helper Classes:

TVirtualStringData (Tee.GridData.Strings)

String grid emulation with Cells[Col, Row] indexing. Usage:

Creating Custom Virtual Data

Implementing a custom adapter requires careful attention to performance and correctness.

Basic Implementation Template

Performance Optimization

AsString is called for every visible cell on every paint. Optimize it ruthlessly:

Data Change Notifications

Use events to notify the grid of changes:

Advanced Features

Master-Detail Support

Custom Sorting

Column Calculations

Testing Virtual Data

Best Practices

  • Store only essential state in TVirtualData
  • Let the original data source own the actual data
  • Clear caches in Refresh method
  • Don’t store TColumn references (they can be freed/recreated)
  • Protect against invalid row/column indices
  • Handle data source disconnection gracefully
  • Return empty string from AsString on errors (don’t raise)
  • Raise exceptions only in SetValue for validation errors
  • TVirtualData methods are called from UI thread only
  • If data source uses background threads, synchronize access
  • Use critical sections for shared state
  • Implement DataType() for proper formatting and editors
  • Use TagObject to store field/property references
  • Return appropriate THorizontalAlign for column types

Next Steps

Data Binding

Understanding the data binding architecture

Custom Data Source

Complete guide to custom implementations

Database Grids

Working with TVirtualDBData

API Reference

Full TVirtualData API documentation