Tuesday, March 20, 2012

VirtualizingDataList – Displaying Large Datasets

In the last few posts I have introduced a number of features from the data framework included as part of the open-source Cocoon framework for Windows 8 Metro-style apps. Following an introduction to the framework I described the SimpleDataListSource and PagedDataListSource.
To recap, the IDataListSource implementations provide a simple way of accessing data from web APIs. These have been designed to reflect the typical structure of such APIs, generally resulting from a series of stateless HTTP requests to retrieve the data, often a page at a time.
In response to data provided from an IDataListSource, the DataList implementations are designed to request and display the information to the user. The aim here is to provide the user experience expected for a client application, with large scrolling lists of items and suitable support for background on-demand data retrieval.

Introducing The VirtualizingDataList

The first DataList implementation provided in the Cocoon data framework is the VirtualizingDataList<T> class. This can be used for situations where a large scrolling list only displays a small subset of the data at any one time. Only the data in view will be retrieved, with more data being fetched on-demand as the user scrolls through this list. In addition it supports the WinRT ISupportPlaceholder interface to indicate to the displaying UI to display a placeholder element whilst data is being retrieved in the background. This builds on top of Cocoon’s VirtualizingVector class so more information on data virtualization and placeholder support can be found in the associated post.
To use a VirtualizingDataList<T> you simply create a new instance, passing the IDataListSource via its constructor. It can then be bound to any of the many controls for displaying lists of information, most commonly the GridView and ListView controls.
If you are following the MVVM presentation pattern then you will expose the data list via a view model,

public class MyViewModel
    // *** Fields ***
    private IList<Person> employees;
    // *** Constructors ***
    public MyViewModel()
        IDataListSource<Person> source = new EmployeesDataListSource();
        employees = new VirtualizingDataList<Person>(source);
    // *** Properties ***
    public IList<Person> Employees
            return employees;

Then in your XAML you can define a CollectionViewSource that binds to the data list, and connect that to your items control,

    <CollectionViewSource x:Name="itemsViewSource" Source="{Binding Employees}"/>
<GridView ItemsSource="{Binding Source={StaticResource itemsViewSource}}" ... />

In fact, this is exactly what the Visual Studio 11 Metro-style XAML templates will produce for you.


In the above discussing I have shown how easy it is to consume any IDataListSource and display it to the user through the fluid scrollable user experience expected of modern applications. When I introduced the Cocoon data framework I discussed “bridging the data divide” between the stateless HTTP calls of web APIs and the continuous scrollable lists displayed to the user. By coding the former as IDataListSource implementations, and the latter as DataLists, Cocoon provides the bridge to span these two worlds.

As usual the code is freely available for download from the Cocoon CodePlex site (to get the latest version go to the “Source Code” tab, select the first change set and use the “Download” link).


Please note that due to a known issue with the Visual Studio templates in the Consumer Preview (see this forum post) they disable virtualization support for the GridView. Therefore although the VirtualizingVector and VirtualizingDataList classes will still work, they unfortunately fetch all items in the collection rather than on demand. To re-enable the virtualization support you can remove the ScrollViewer that surrounds the GridView, however this will clip elements a little strangely. Hopefully this will be resolved in the final release of Visual Studio, although I am working on a temporary workaround.
Post a Comment