Wednesday, December 14, 2011

Data Virtualization in Metro-style apps with ISupportPlaceholder

Update 8th April 2012 : Modified to reflect changes upon release of Windows 8 Consumer Preview - References to IVirtualizingVector replaced with ISupportPlaceholder.

In my last post I introduced an implementation of the IObservableVector<T> interface that allows Windows 8 Metro-style applications to automatically update data bound XAML items controls as the underlying data source changes. In this post I am going to delve one stage deeper by demonstrating an implementation of the ISupportPlaceholder interface that enables data virtualization

A Background to Data Virtualization

To start I will provide some background to data virtualization and explain why this is becoming essential for modern applications to improve performance with large data sets. In a traditional, non-data-virtualized application, lists of data must be fully loaded into memory before they can be displayed to the user. When this data is held in a local database or file system this may mean loading many hundred items into memory before being shown in the user interface. With modern cloud-connected applications this becomes more of an issue as they must all be downloaded across what is a relatively slow connection.
In web applications this problem has been solved by the concept of paging – only a small number of items are shown at any one time, and the user can move between the pages by following links. In client based applications however the user expects a more seamless experience – a single list that can be scrolled through as desired.
Data virtualization solves this problem by only downloading and storing in memory the data that is required, deferring the download of further items until they are scrolled into view. The user sees a single list as if they are viewing the total data set, however as they move through the list any newly visible items are obtained on demand.

Data Virtualization for Metro-Style Apps

In Windows 8, Metro style applications support virtualized lists through the ISupportPlaceholder interface,

public interface ISupportPlaceholder
{
    bool IsPlaceholder(object item);
}

At first sight it is not immediately obvious how this can be used to virtualize a list, however it provides the vital link between a virtualization aware data set and a data bound user interface. An ISupportPlaceholder implementation is responsible for providing any data virtualization logic,


  • In general the list should behave as you would expect for an IObservableVector<T> implementation
  • When the items are requested the list should return the actual item if this is available, or a placeholder item if it has yet to be downloaded
  • The IsPlaceholder(…) method may then be called with each item returned in the list, and the ISupportPlaceholder implementation should return true if this is a placeholder item, otherwise false
  • It is also the responsibility of the  ISupportPlaceholder implementation to download any requested items in the background and update the list as these are available.

In return the standard Metro-style items controls will show any items for which IsPlaceholder(…) returns true as a grey rectangle,



An ISupportPlaceholder Implementation


To assist with data virtualization in .Net based Metro-style applications a base implementation is provided as part of the freely available Cocoon framework. This is provided as the Cocoon.Data.VirtualizingVector abstract class, into which you simply provide your custom data retrieval logic. You will either be requested for the number of items in the list or a specific item, and once obtained should then call the UpdateCount(…) or UpdateItem(…) methods

public class PersonCollection : VirtualizingVector
{
    protected override void FetchCount()
    {
        // Perform custom code here to retrieve
        //     the number of items in the dataset
 
        UpdateCount(itemCount);
    }
 
    protected override void FetchItem(int index)
    {
        // Perform custom code here to retrieve
        //     the specified item from the dataset
 
         UpdateItem(index, retrievedItem);
    }
}

The VirtualizingVector class then takes care of implementing IObservableVector<T> and ISupportPlaceholder, returning of suitable placeholder objects for items as they are requested, and updating items with real data as it is made available.

Of course this approach would still consume large amounts of memory when displaying a list with a large number of placeholder items. The VirtualizingVector class overcomes this by using the provided VirtualizingList<T> implementation. Without going into detail, this behaves as you would expect for a list with a large number of elements, whilst allocating memory efficiently to store only those items that are not virtualized.

Summary


In conclusion, the Cocoon framework provides an ISupportPlaceholder implementation designed to enable data virtualization for Metro-style applications. 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).
In my introduction to the Cocoon framework I stated that one of my aims was to bridge the divide between the stateless paging model of most web APIs and the “fast and fluid” interfaces of Metro-style applications. Now that I have provided the fundamentals, next time I will try to bridge this gap by introducing “data lists” and “data list sources”.

Thursday, December 01, 2011

ObservableVector as a replacement for ObservableCollection in Metro-style apps

For those of you who have had previous experience in making WPF and Silverlight applications you are probably familiar with the ObservableCollection<T> class. This represents a list of items (implementing IList<T>) whilst also raising the INotifyCollectionChanged.CollectionChanged event whenever items are added, removed or moved within the collection. When such collections are databound to the various list controls in WPF and Silverlight the UI will automatically update to reflect any changes.

ObservableCollection<T> and Metro-Style Apps

If you have followed the same technique when writing Windows 8 Metro-style apps you will have found that this no longer works. There are a couple of reasons for this behaviour,

  1. In the Developer Preview version of Windows 8 the INotifyPropertyChanged interface is duplicated in both the System.ComponentModel and Windows.UI.Xaml.Data namespaces. Whilst ObservableCollection<T> implements the former, the new Metro XAML framework uses the latter.
  2. Rather than INotifyCollectionChanged as implemented by ObservableCollection<T>, WinRT uses the IObservableVector<T> interface.

Observable Collections in Metro-Style Apps

Whilst this issue is likely to be addressed prior to release of Windows 8, for the time being there are a few workarounds.

  1. The Windows 8 SDK Data Binding sample includes an ObservableVector class that takes an existing object that implements INotifyCollectionChanged, and wraps it in an IObservableVector<T> implementation.
  2. Colin Eberhardt has posted a similar solution on his blog.
  3. Avi Pilosof has taken a slightly different approach by deriving a new class from ObservableCollection<T>, implementing both INotifyCollectionChanged and IObservableVector<T>.

Whilst these solve the problem, they all involve wrapping the existing ObservableCollection<T> class, resulting in events being raised for both the old and new approaches. This is ideal for cases where you wish to write interoperable code for both existing and Metro applications, but is an added overhead when you are natively writing a new Windows 8 application.

A Metro-Designed Observable Collection Class

In response to this I have written a ground-up ObservableVector<T> class for use in Windows 8 Metro-style applications that does not have the overhead of an underlying ObservableCollection<T>. The code has been released as part of the freely available Cocoon framework. You can use this class by creating a new instance directly,

IList<Person> list = new ObservableVector<Person>();
list.Add(new Person("Andrew", "Wilkinson"));


or by deriving a custom class,



public class PersonCollection : ObservableVector<Person>
{
    ...
}


It is important to note however that in the current Windows Developer Preview there is a bug which means that databinding only works correctly to lists when the implement ObservableVector<object> rather than strongly typed collections. This is likely to change in the future.


In both cases the behaviour is designed to match that expected by WPF and Silverlight developers. There are a small number of subtle differences with respect to the previous ObservableCollection<T> class,



  1. Since IObservableVector<T> does not have the same concept of moving items it does not implement the Move() method. Instead you should remove the item and then add it to its new place in the collection.

  2. The constructor of the ObservableVector<T> class optionally accepts an IList<T> that is wrapped by the implementation rather than copied internally – the reason for this will become apparent in later posts.

  3. Currently no attempts are made to stop VectorChanged event handlers from modifying the original collection.

Summary


In conclusion, the Cocoon framework provides an IObservableVector<T> implementation specifically designed from the ground-up for Metro applications. 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).


Next time I will discuss data virtualisation and the IVirtualizingVector interface.

Sunday, November 27, 2011

Cocoon – A new framework for Windows 8 Development

Regular followers of my blog will know that over the last year I have been discussing a framework that I introduced for Windows Phone 7 development named Chrysalis (http://chrysalis.codeplex.com/). Whilst not a Model-View-ViewModel (MVVM) framework itself, allowing the use of your preferred framework for this purpose, it was designed to enable view models to interact with the phone lifecycle and hardware in a simple and natural manner.

Following the announcement of the Windows 8 Metro-style application programming model at Microsoft’s //build conference, it became clear that many of the same challenges would present themselves for Windows 8 applications.

The Cocoon Framework

To assist with Windows 8 Metro-style applications I would like to announce the Cocoon framework (http://cocoon.codeplex.com/). This aims to build on top of the learning from the Chrysalis project to provide a simple way to develop Metro-style applications in a manner that fits naturally with the MVVM design pattern.

It is likely that many Metro-style apps will be connected applications, downloading data from across the internet in response to user navigation. Modern applications are expected to do this in a seamless manner, retrieving data on demand and populating the user interface in response. In some ways this is at odds with the web API programming model that is based upon individual request-response calls, with paging used to retrieve large datasets. One of the first targets of the Cocoon framework is to simplify this process – bridging the world of stateless web API calls, with the “fast and fluid” interfaces expected by users.

Cocoon Framework Development

Since Windows 8 is currently at an early stage, it is anticipated that the Cocoon framework will evolve alongside further releases. If functionality is introduced in the platform that duplicates that within the Cocoon framework, efforts will be made to migrate to the platform support whenever possible.

It is an exciting time for Windows developers, with the upcoming release of Windows 8 ushering in a new ecosystem of applications. The Cocoon framework will allow you to focus on your individual business logic, whilst ensuring that the user experience fully supports the richness of the platform.

Summary

To conclude, the first source-code drops of the Cocoon framework are freely available on CodePlex (http://cocoon.codeplex.com/). As the project evolves, new functionality will be explained on this blog so stay tuned.

Tuesday, October 25, 2011

Chrysalis – Injection of Application Services and State

In my last post I introduced the concept of application and session state within a Windows Phone 7 application, and described how the Chrysalis framework makes it easy to share state between multiple pages (and hence view models) within an application, including full tombstoning support. As usual, all the source code is available on the Chrysalis CodePlex site under the “Source Code” tab.

Application Services

To recap, Chrysalis allows multiple view models to share the same state between multiple pages by using one of the two ChrysalisService.GetService methods,

   1: public class ChrysalisService
   2: {
   3:      ...
   4:  
   5:      public T GetService<T>() { ... }
   6:      public object GetService(Type serviceType) { ... }
   7:  
   8:      ...
   9: }

The first time one of these methods is called, a new instance of the specified type is created (calling the default parameter-less constructor). Any subsequent calls will return the same “singleton” instance. As the method names allude to, this can be used not only for general state, but for any services that may wish to be shared throughout the application.


Furthermore, Chrysalis makes it simple for these services to persist state when the application is tombstoned. All that is required is for the service to implement the IHasSessionState interface,



   1: public interface IHasSessionState
   2: {
   3:     // *** Methods ***
   4:  
   5:     void Initialize(object state);
   6:     object SaveState();
   7: }

The first time the service is created within a session the Initialize method is called with the state parameter set to null. In this instance default values can be set along with any other initialization required by the service. Upon tombstoning the SaveState method is called from which you can return any state you wish to persist. Upon reactivation this state is passed back to the newly created instance of the service (remember – during tombstoning the application process is killed and all objects are lost) via the Initialize method.


Chrysalis and Dependency Injection


Whilst the ChrysalisService class provides the GetService methods, this is only one way in which your view models can obtain such state information. Another method is “dependency injection”. This refers to a situation where external dependencies (in our case the state objects) are injected into our view model, rather than the view model itself having to seek them out.


In Chrysalis this is done by defining public properties for each of the services that we wish to inject into the view model. To indicate that these should be injected we add the [ChrysalisImport] attribute to the property. Finally, in the constructor we check whether Chrysalis is initialised and tell the ChrysalisService to satisfy any imports by calling the SatifyImports(…) method.


For example within the sample CalculatorViewModel included with the source download,



   1: public class CalculatorViewModel : ViewModelBase, IHasSessionState
   2: {
   3:     // *** Constructors ***
   4:  
   5:     public CalculatorViewModel()
   6:     {
   7:         if (ChrysalisService.Current != null)
   8:             ChrysalisService.Current.SatisfyImports(this);
   9:     }
  10:  
  11:     // *** Properties ***
  12:  
  13:     ...
  14:  
  15:     [ChrysalisImport]
  16:     public CalculatorSessionState SessionState
  17:     {
  18:         get;
  19:         set;
  20:     }
  21:  
  22:     ...
  23: }

This defines a property called SessionState that is marked with the [ChrysalisImport] attribute. In the constructor we notify Chrysalis that it should inject any dependencies, which when it returns will have set the property to an instance of CalculatorSessionState. As with the GetService calls this will return the same instance across all view models, creating a new object only if this is the first such reference. Note that you can define any number of properties to be injected and they will all be satisfied by the one SatisfyImports(…) call.


Using Interfaces for Dependency Injection


Whilst being able to declaratively inject singleton instances of classes is useful, there are a number of reasons that you would wish to decouple such properties from the concrete implementations – for example to inject mock implementations for testing purposes. This is usually done by specifying an interface rather than a class type, and this too is enabled in the Chrysalis framework.


For example in the ChoosersViewModel sample included in the source code,



   1: [ChrysalisImport]
   2: public IChooserExecutionService ChooserExecutionService
   3: {
   4:     get;
   5:     set;

6: }


However, we now need a way to link the interface to the concrete implementation. In the Chrysalis framework this is done by simply attributing the interface with the ExportImplementationAttribute specifying the concrete type to use.



   1: [ExportImplementationAttribute(typeof(ChooserExecutionService))]
   2: public interface IChooserExecutionService
   3: {
   4:     ...
   5: }

 


Comparing Chrysalis with Other Dependency Injection Frameworks


Before I conclude I would like to take a moment to contrast dependency injection in the Chrysalis framework to other implementations. Dependency injection within Chrysalis was designed to support the very basic injection of services (to enable unit testing, etc.) and integration with the rest of the Chrysalis model – this it performs well. If you require more advanced services then it is recommended that you use a full dependency injection container implementation.