Category Archives: Portable Class Library

Windows 8, Portable Class Libraries and ISupportIncrementalLoading

In my previous two posts (Win RT, Commanding and Cross Platform Apps Part 1 and Platform Specific Code and Portable Class Libraries) I extolled the virtues of adopting a view model approach and keeping a clean separation between your platform specific code and your view models.

For the most part it works pretty simply with a rich enough section of .Net available across most portable class library profiles however every now and then you’ll come across something that looks to be glued deeply into the platform and that isn’t immediately obvious how to best decouple.

Adopting ISupportIncrementalLoading recently caught me out like this. In Windows 8 controls such as GridView and ListView look for this interface to be defined on the collection model they are bound to. If it’s found then after the initial set of items in the collection are bound and displayed they will repeatedly call the interface (usually as you scroll towards the end) to fetch additional items asynchronously.

It’s simple to implement other than one drawback: it’s a very Windows 8 specific feature and isn’t available from a portable class library.

So how to tackle this?

I normally adopt one of two approaches: proxy classes accessed via value converters or dependency injected factories.

All of the below examples come from a side project I’ve been working on and that I’ll be releasing as open source shortly – so if you want to see this all in a real world context you will be able to soon.

The Proxy Class Approach

In this approach, and continuing to use ISupportIncrementalLoading as an example, we would implement a class within our platform specific Windows 8 UI layer that supports the necessary interfaces for ISupportIncrementalLoading (IList, INotifyCollectionChanged and ISupportIncrementalLoading itself) and routes most of the calls down to your view model in a cross-platform friendly manner.

During binding you then use a ValueConverter to wrap the underlying view model in your proxy class as in the below sample:

public class StoryCollectionValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        StoryCollection storyCollection = value as StoryCollection;
        if (storyCollection != null)
        {
            return new IncrementalLoadingObservableCollectionProxy<StoryViewModel>(storyCollection);
        }
        throw new InvalidCastException("Value is not of type StoryCollection");
    }
 
    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

Using this example my view model simply declares a property of type StoryCollection and this gets replaced during binding by the proxy class IncrementalLoadingObservableCollectionProxy that implements the ISupportIncrementalLoading interface – I won’t show this latter class as it becomes quite big.

The advantage of this approach is that it keeps your view model code uncluttered. It needs to undertake no special behaviour to account for the host platform. The downside, in the case of ISupportIncrementalLoading, is that because the proxy is of a collection and an implementation of the other two interfaces it gets quite large and unwieldy.

The Factory Approach

If you remember from the post on Bait and Switch PCLs a portable class library always runs within a non-portable framework and so although you can’t access the functionality of that framework directly from the code in the library you can use techniques such as dependency injection to access it.

The factory approach to this problem takes advantage of this by declaring an IIncrementalLoadingCollectionFactory interface in a portable class library but providing the implementation for it in a Windows 8.1 assembly. My factory implementation looks like this:

internal class IncrementalLoadingCollectionFactory : IIncrementalLoadingCollectionFactory
{
    private readonly IUserInterfaceDispatcher _dispatcher;
 
    public IncrementalLoadingCollectionFactory(IUserInterfaceDispatcher dispatcher)
    {
        _dispatcher = dispatcher;
    }
 
    public ObservableCollection<T> GetCollection<T>(Func<ObservableCollection<T>, uint, Task<IncrementalLoadingResult<T>>> fetchMoreFunc)
    {
        return new IncrementalLoadingCollection<T>(_dispatcher, fetchMoreFunc);
    }
}

You can see that it returns a collection called IncrementalLoadingCollection that is constructed with a function that is responsible for adding items to the collection.

My IncrementalLoadingCollection looks like this:

public class IncrementalLoadingCollection<T> : ObservableCollection<T>, ISupportIncrementalLoading
{
    private readonly IUserInterfaceDispatcher _dispatcher;
    private readonly Func<ObservableCollection<T>, uint, Task<IncrementalLoadingResult<T>>> _fetchMoreFunc;
 
    public IncrementalLoadingCollection(IUserInterfaceDispatcher dispatcher, Func<ObservableCollection<T>, uint, Task<IncrementalLoadingResult<T>>> fetchMoreFunc)
    {
        _dispatcher = dispatcher;
        _fetchMoreFunc = fetchMoreFunc;
        HasMoreItems = true;
    }
 
    public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
    {
        return Task.Run(async () =>
        {
            IncrementalLoadingResult<T> result = await _fetchMoreFunc(this, count);
            HasMoreItems = result.HasMoreItems;
 
            await _dispatcher.DispatchAsync(() =>
            {
                foreach (T item in result.ItemsLoaded)
                {
                    Add(item);
                }
 
                return Task.FromResult(0);
            });
 
            return new LoadMoreItemsResult {Count = (uint)result.ItemsLoaded.Count()};
        }).AsAsyncOperation();
    }
 
    public bool HasMoreItems { get; private set; }
}

It’s a fairly minimal class that simply calls the supplied function and adds the items to the observable collection and I use all the above from my portable class library view model layer as follows:

model.FilteredStories = _incrementalLoadingCollectionFactory.GetCollection<StoryViewModel>(async (collection, count) =>
{
    IncrementalLoadingResult<StoryViewModel> result = new IncrementalLoadingResult<StoryViewModel>();
    IncrementalStories increment = await _readerCoordinator.FetchMoreStoriesAsync(model, count);
    result.ItemsLoaded = new List<StoryViewModel>();
    result.HasMoreItems = increment.HasMoreStories;
 
    if (increment.Stories.Any())
    {
        await _userInterfaceDispatcher.DispatchAsync(() =>
        {
            model.AllStories.AddRange(increment.Stories);
            List<StoryViewModel> filteredNewStories = 
                _filterBuilder
                    .Filter(_readerCoordinator.ReaderViewModel, increment.Stories)
                    .OrderByDescending(x => x.PostedAt)
                    .ToList();
            result.ItemsLoaded = filteredNewStories;
 
            return Task.FromResult(0);
        }, true);
    }
    return result;
});

In the specific example of ISupportsIncrementalLoading I prefer the factory approach as the proxy boilerplate is lengthy and you then still need to deal with linking your view model to your proxy in order to actually get the incremental results.