Home > C#, WinRT > Implementing the ISupportIncrementalLoading interface in a Windows Store app

Implementing the ISupportIncrementalLoading interface in a Windows Store app

22/05/2013

The ISupportIncrementalLoading interface allows to easily create a collection in which data is loaded incrementally, when a user is about to the end of the items available on the user interface. Using it, we can obtain a fast & fluid scrolling while loading an huge set of records.

First of all, we need a class that inherits from ObservableCollection and implements the ISupportIncrementalLoading interface:

public interface IIncrementalSource<T>
{
    Task<IEnumerable<T>> GetPagedItems(int pageIndex, int pageSize);
}

public class IncrementalLoadingCollection<T, I> : ObservableCollection<I>, 
     ISupportIncrementalLoading
     where T : IIncrementalSource<I>, new()
{
    private T source;
    private int itemsPerPage;
    private bool hasMoreItems;
    private int currentPage;

    public IncrementalLoadingCollection(int itemsPerPage = 20)
    {
        this.source = new T();
        this.itemsPerPage = itemsPerPage;
        this.hasMoreItems = true;
    }

    public bool HasMoreItems
    {
        get { return hasMoreItems; }
    }

    public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
    {
        var dispatcher = Window.Current.Dispatcher;

        return Task.Run<LoadMoreItemsResult>(
            async () =>
            {
                uint resultCount = 0;
                var result = await source.GetPagedItems(currentPage++, itemsPerPage);

                if (result == null || result.Count() == 0)
                {
                    hasMoreItems = false;
                }
                else
                {
                    resultCount = (uint)result.Count();

                    await dispatcher.RunAsync(
                        CoreDispatcherPriority.Normal,
                        () =>
                        {
                            foreach (I item in result)
                                this.Add(item);
                        });
                }

                return new LoadMoreItemsResult() { Count = resultCount };

            }).AsAsyncOperation<LoadMoreItemsResult>();
    }
}

The ISupportIncrementalLoading interface defines a property and a method:

  • HasMoreItems is used to determine if the collection has more available items;
  • LoadMoreItemsAsync is the method that actually performs the incremental loading. This method is invoked every time the control the collection is attached to needs more items to show. For example, if we are using a GridView, when the scroll reaches the edge of the screen, after having checked the HasMoreItems property, it calls the LoadMoreItemsAsync method and await for the end of the operation.

At line 35, LoadMoreItemsAsync calls the GetPagedItems method defined in the IIncrementalSource interface. We need to create a class that implements it and provides the items based on page index and page size. If this method returns a null or 0-length collection, we assume that no more items are available. Otherwise, we add the items to the ObsersevableCollection, so that the CollectionChanged event will be raised to update the user interface.

Let’s see how to use these classes. Suppose to have a Person class:

public class Person
{
    public string Name { get; set; }
}

In order to incrementally load a collection of this object, we define the following class:

public class PersonSource : IIncrementalSource<Person>
{
    private List<Person> persons;

    public PersonSource()
    {
        persons = new List<Person>();

        for (int i = 0; i < 1024; i++)
        {
            var p = new Person { Name = "Person " + i };
            persons.Add(p);
        }
    }

    public async Task<IEnumerable<Person>> GetPagedItems(int pageIndex, int pageSize)
    {
        return await Task.Run<IEnumerable<Person>>(() =>
            {
                var result = (from p in persons
                              select p).Skip(pageIndex * pageSize).Take(pageSize);

                return result;
            });
    }
}

In this simple example, we create a list of Person in the constructor and, in the GetPagedItems method, we return portions of it according to the values of pageIndex and pageSize parameters. In a real scenario, of course, the GetPagedItems will tipically call an external service to retrieve data.

Now the only thing left to do is to create the IncrementalLoadingCollection and assign it to the ItemsSource property of the GridView:

var collection = new IncrementalLoadingCollection<PersonSource, Person>();
gridView.ItemsSource = collection;

Note that also the ListView control can be bound to collections that implements the ISupportIncrementalLoading interface.

Categories: C#, WinRT
  1. Simon
    10/06/2013 at 13:06

    You just saved my day (and my app from loading 1733 items in ListView)

    • 10/06/2013 at 13:11

      I’m happy to have helped you!

  2. Rahul Saksule
    15/07/2013 at 14:33

    Its a good tutorial to start with.

  1. 23/05/2013 at 09:25
  2. 23/05/2013 at 11:38
Comments are closed.