ComponentOne Xamarin Edition
Incremental Loading
Controls > CollectionView > Features > Incremental Loading

Incremental loading or on-demand loading is a powerful feature for mobile applications where data is loaded in chunks as the user scroll down a list in real time. Xamarin CollectionView supports incremental loading for data bound controls, such as FlexGrid and UITableView.

Adding incremental loading to ListView control is accomplished in two basic steps.

  1. Implement your own collection view class, for example, OnDemandCollectionView, that extends C1CursorCollectionView class and overrides GetPageAsync. Once, this is completed you need to add logic that loads the data in pages or chunks.

  2. Extend UITableView, FlexGrid, or another UI control to determine when the user has reached the bottom of a page.

The following GIF image shows incremental loading in FlexGrid control.

The following code example demonstrates how to implement incremental loading using the CollectionView class.

  1. Add a new Content Page, IncrementalLoading.xaml to your project.
  2. To initialize a ListBox control and enabling incremental loading, modify the markup between the <ContentPage></ContentPage> as shown below.

    In XAML

    XAML
    Copy Code
    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="XamarinSample.IncrementalLoading"
                 Title="Incremenatl Loading">
        <ListView x:Name="list">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextCell Text="{Binding ItemName}" Detail="{Binding ItemDateTime, 
               StringFormat='Created: {0}'}" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </ContentPage>

  3. In the Solution Explorer, expand the IncrementalLoading.xaml node and open IncrementalLoading.xaml.cs to open the C# code behind.
  4. Add the following code in the IncrementalLoading class constructor to implement on demand loading in the LostBox control:

    In Code

    C#
    Copy Code
    public partial class IncrementalLoading : ContentPage
            {
                    public IncrementalLoading ()
                    {
                            InitializeComponent ();
    
                var myCollectionView = new SimpleOnDemandCollectionView();
                list.ItemsSource = myCollectionView;
    
                list.LoadItemsOnDemand(myCollectionView);
            }
            }
        public class SimpleOnDemandCollectionView : C1CursorCollectionView<MyDataItem>
        {
            const int MAX = 100;
            int current;
            public SimpleOnDemandCollectionView()
            {
                PageSize = 20;
            }
    
            public int PageSize { get; set; }
           
    
            protected override async Task<Tuple<string, IReadOnlyList<MyDataItem>>> GetPageAsync(int startingIndex, string pageToken, int? count = null, IReadOnlyList<SortDescription> sortDescriptions = null, FilterExpression filterExpression = null, CancellationToken cancellationToken = default(CancellationToken))
            {
                if (startingIndex >= MAX)
                    return new Tuple<string, IReadOnlyList<MyDataItem>>(null, null);
               
                var newItems = new ObservableCollection<MyDataItem>();
                await Task.Run(() =>
                {
                    for (int i = 0; i < this.PageSize; i++)
                    {
                        if (current >= MAX)
                            break;
                        newItems.Add(new MyDataItem(startingIndex + i));
                        current++;
                    }
                });
                return new Tuple<string, IReadOnlyList<MyDataItem>>("token not used", newItems);
    
            }
        }
        public class MyDataItem
        {
            public MyDataItem(int index)
            {
                this.ItemName = "My Data Item #" + index.ToString();
                this.ItemDateTime = DateTime.Now;
            }
            public string ItemName { get; set; }
            public DateTime ItemDateTime { get; set; }
    
        }
        public static class ListViewEx
        {
            public static void LoadItemsOnDemand<T>(this ListView listview,
             C1CursorCollectionView<T> collectionView) where T : class
            {
                listview.ItemAppearing += (s, e) =>
                {
                    var index = collectionView.IndexOf((T)e.Item);
                    if (index == collectionView.Count - 1)
                    {
                        if (collectionView.HasMoreItems)
                        {
                            collectionView.LoadMoreItemsAsync();
                        }
                    }
                };
                listview.Refreshing += async (s, e) =>
                {
                    listview.IsRefreshing = true;
                    await collectionView.RefreshAsync();
                    listview.IsRefreshing = false;
                };
                if (collectionView.HasMoreItems)
                {
                    collectionView.LoadMoreItemsAsync();
                }
            }
        }