GridControl tutorial part4: Virtualization

Microsoft Wpf framework is an absolutely new data presentation system as compared to all previous versions of control libraries. All previous libraries (such as MFC or Winforms) were based on window message processing. The main method of data display and painting was usage of CDC object in MFC or its counterpart Graphics in WinForms. WPF brought radical changes to the rendering system. For data display purposes every control now consists of a set of simpler controls presented as a Visual tree. They are rendered via graphics processor (GPU) using DirectX. It means that the data presentation model has completely changed. Dapfor Wpf GridControl is a control that can display many hundred thousands rows, each of which may contain multiple cells. Without virtualization the grid would consume too much memory and CPU/GPU resources.

For data display purposes the grid has its own internal control hierarchy that is built as a visual tree. All these controls have the form of classes that inherit from Control. An illustration of this hierarchy is shown on figure below.

The number of control on the above image depends only on visible grid size. Actual data volume may be significantly greater than the number of controls visible in the visual tree. That is why virtualization with data templates is used to display all data.

When adding data to the grid or binding data sources, the grid creates a collection of objects of Row class. Each of these objects defines hierarchy and state (expansion/filtering/ selection, etc). Row is not a control and the number of objects of this class depends on volume of data in the grid. Therefore, row object takes as little memory as possible (about 150 bytes, which is equivalent to about 15 Mb per 100,000 data objects). Object of Row class also provides a convenient API for determining data location in the grid and for changing state, filtering, highlighting, etc. Row also contains Cell collection that provides access to values returned by data object properties and provide API for data highlighting for specified period of time.

Below we provide a few examples of adding data to the grid:

C# 

private void grid_Initialized(object sender, EventArgs e) 
{
//Add an array of objects on the top level
Row row = grid.Rows.Add(new object[] { 10, 11.12, "some string 1" });

//Add a dictionary as a child object
IDictionary<string, object> dataObject2 = new Dictionary<string, object>();
dataObject2.Add("IntValue", 20);
dataObject2.Add("DoubleValue", 21.33);
row.Add(dataObject2);

//Add an object with variable number of fields as a child of the row
Row childRow = row.Add(new UnboundValueAccessor());
childRow["StringValue"].Value = "some value";
}

C# 
private void grid_Initialized(object sender, EventArgs e) 
{
//Build and attach data BindingList<MyCustomClass>
bindingList = new BindingList<MyCustomClass>();
bindingList.Add(new MyCustomClass(10, 11.12, "some string 1"));
bindingList.Add(new MyCustomClass(20, 21.33, "some string 2"));

grid.ItemsSource = bindingList;
}

Data can also be added via xaml-code:

XAML 

<Window x:Class="TestApplication.Tutorial.DataTypesWindow" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Objects of arbitrary classes" Height="352" Width="671"
xmlns:df="clr-namespace:Dapfor.Wpf.Controls;assembly=Dapfor.Wpf"
xmlns:Tutorial="clr-namespace:TestApplication.Tutorial">

<Window.Resources>
<Tutorial:MyCollection x:Key="myCollection"/>
</Window.Resources>

<df:GridControl Name="grid" ItemsSource="{StaticResource myCollection}">
<df:GridControl.Headers>
<df:Header ScrollType="Stretch">
<df:Header.Columns>
<df:Column Id="Id0" Title="Column 0" />
<df:Column Id="Id1" Title="Column 1" />
<df:Column Id="Id2" Title="Column 2" />
</df:Header.Columns>
</df:Header>
</df:GridControl.Headers>
</df:GridControl>
</Window>

For more details about data binding see here.

Virtualization in Dapfor Wpf GridControl means that controls display only visible part of Row class and Cell objects depending on vertical and horizontal scrollbar position. Connection of controls to row and cell objects is done with data templates and data template selectors.

An example of data template usage:

XAML 
<Window x:Class="TestApplication.Window1" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:df="clr-namespace:Dapfor.Wpf.Controls;assembly=Dapfor.Wpf"
xmlns:TestApplication="clr-namespace:TestApplication"
Title="Window1" Height="427" Width="724">

<Window.Resources>
<!--Declare a collection of data objects-->
<TestApplication:MyCollection x:Key="someCollection" />

<!--Easiest cell data template-->
<DataTemplate x:Key="cellTemplate">
<Grid> <Ellipse Fill="Green"/>
<TextBlock Text="{Binding Path=Text}" HorizontalAlignment="Center" Foreground="Red"/>
</Grid>
</DataTemplate>
</Window.Resources>

<!--Use GridControl as a single child of Window1 -->
<df:GridControl Name="grid" ItemsSource="{StaticResource someCollection}">
<df:GridControl.Headers>
<df:Header>
<df:Header.Columns>
<df:Column Id="Value1" Title="Column 0" CellTemplate="{StaticResource cellTemplate}" Width="100" />
<df:Column Id="Value2" Title="Column 1" Width="100" />
</df:Header.Columns>
</df:Header>
</df:GridControl.Headers>
</df:GridControl>
</Window>

cell data templates

Back to Wpf GridControl tutorial