Infinite Scrolling in Windows Store Apps Using ISupportIncrementalLoading – Boredom Challenge Day 26

Standard

In my previous blog post we’ve seen how we can implement pagination in Windows Store Apps by using a FlipView, but that is actually kind of against the design principles of WinRT and that solution may not be always desirable for you. So you may want a GridView or ListView that incrementally loads their items as the user progresses through it, just like your main page in Facebook where you infinitely get the past items as your scroll lower and lower.

For example, my blog incrementally loads 7 posts as you scroll through. If you scroll quickly, you'll see the loading icon in the lower left and then the previous 7 blog posts will appear.

For example, my blog incrementally loads 7 posts as you scroll through. If you scroll quickly, you’ll see the loading icon in the lower left and then the previous 7 blog posts will appear.

Ok then, we want this feature in our Windows Store Apps. One direct approach would be using an ObservableCollection, then constantly checking the how much the GridView is scrolled, and if it is scrolled enough, loading the new items by adding them to the ObservableCollection. However, although that makes sense, trying to implement it manually is not really a good idea, especially when we have an interface made just for this purpose: ISupportIncrementalLoading (lol it’s like saying “I support incremental loading.”… Ok, that was lame).

Anyway, in this article, we’ll create an example app to see how we can use ISupportIncrementalLoading interface to load items incrementally so our user can scroll infinitely.

Let’s start by taking a look at the ISupportIncrementalLoading interface, which is actually quite simple:

        public interface ISupportIncrementalLoading
        {
            bool HasMoreItems { get; }
            IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count);
        }

We have one property and one method in the interface. HasMoreItems property (actually, its getter) is where we will be checking if we have more items to load incrementally, and LoadMoreItemsAsync method is where we will fetch the items and add them to the GridView or ListView. Also keep in mind that while fetching the items we are free to do anything we want, so you can add filters or do other operations on the items here as you wish (though if you in any way change the number of added items, it would result in uneven number of items being added in each loading operation (though users probably won’t feel it if there are many items)).

Alright, let’s start our app by creating a blank Windows Store app project in Visual Studio.

2

On the interface side, we’ll just have a GridView to show the items and a ProgressBar to show that the items are being loaded, in MainPage.xaml:

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <GridView x:Name="GridViewMain" Margin="0,100,0,0" Padding="100,0,0,10">
            <GridView.Resources>
                <DataTemplate x:Key="DataTemplateGridViewMain">
                    <Grid Width="100" Height="100" Background="#FF7C1A9B">
                        <TextBlock Text="{Binding}" VerticalAlignment="Center" FontSize="20" FontFamily="Tempus Sans ITC" TextAlignment="Center"/>
                    </Grid>
                </DataTemplate>
            </GridView.Resources>
            <GridView.ItemTemplate>
                <StaticResource ResourceKey="DataTemplateGridViewMain"/>
            </GridView.ItemTemplate>
        </GridView>
        <ProgressBar x:Name="ProgressBar" Height="10" Margin="0,5,0,0" VerticalAlignment="Top" Visibility="Collapsed"/>
    </Grid>

In order to use the ISupportIncrementalLoading interface, we’ll change the way we load our items. Instead of filling a List or ObservableCollection and setting the ItemsSource of the GridView, we’ll create a class that implements ObservableCollection and ISupportIncrementalLoading, handle the loading logic in that class, and set the ItemsSource of the GridView to an instance of that class. That class will look like this:

using System.Collections.ObjectModel;
using Windows.UI.Core;
using System.Threading.Tasks;
        public class ItemsToShow : ObservableCollection<string>, ISupportIncrementalLoading
        {
            public int lastItem = 1;

            public bool HasMoreItems
            {
                get
                {
                    if (lastItem == 10000)
                    {
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
            }

            public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
            {
                ProgressBar progressBar = ((Window.Current.Content as Frame).Content as MainPage).ProgressBar;

                CoreDispatcher coreDispatcher = Window.Current.Dispatcher;

                return Task.Run<LoadMoreItemsResult>(async () =>
                    {
                        await coreDispatcher.RunAsync(CoreDispatcherPriority.Normal,
                            () =>
                            {
                                progressBar.IsIndeterminate = true;
                                progressBar.Visibility = Visibility.Visible;
                            });

                        List<string> items = new List<string>();
                        for (int i = 0; i < count; i++)
                        {
                            items.Add(String.Format("Item {0}", lastItem));
                            lastItem++;
                            if (lastItem == 10000)
                            {
                                break;
                            }
                        }

                        await coreDispatcher.RunAsync(CoreDispatcherPriority.Normal,
                            () =>
                            {
                                foreach (string item in items)
                                {
                                    this.Add(item);
                                }
                                progressBar.Visibility = Visibility.Collapsed;
                                progressBar.IsIndeterminate = false;
                            });

                        return new LoadMoreItemsResult() { Count = count };
                    }).AsAsyncOperation<LoadMoreItemsResult>();
            }
        }

Here, we’ve decided that we’ll have 9999 items starting with 1, and returned false in HasMoreItems property’s get function if we reached it. In LoadMoreItemsAsync, we asynchronously fetched the items and filled our ObservableCollection. Keep in mind that any action that requires us to manipulate the UI needs to be run in CoreDispatcher, because since it is asynchronous the code will be running in another thread and we’ll get a nice exception if we try to reach the UI from anywhere except the UI thread.

The final thing we need to do is to set the ItemsSource of the GridView to an instance of our ItemsToShow class:

        public MainPage()
        {
            this.InitializeComponent();
            this.Loaded += MainPage_Loaded;
        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            GridViewMain.ItemsSource = new ItemsToShow();
        }

Alright then, let’s run the app and try scrolling to the right all the way to 9999 (our item size is small so it is likely that we’ll create hundreds of items to fill the screen when we start the app, and this may cause some stuttering). In the screenshots, look at the size of the scroll bar of the GridView at the bottom of the page when the number of items increase.

3

4

5

6

As you can see, we scrolled until we came to the item 9999 and stopped there since we didn’t have any more items to display. It was easy to use, right? 🙂

You can get the source code of the example from here.

Thank you for reading.

8 thoughts on “Infinite Scrolling in Windows Store Apps Using ISupportIncrementalLoading – Boredom Challenge Day 26

Comment