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.
The following GIF image shows incremental loading in FlexGrid control.
The following code example demonstrates how to implement incremental loading using the CollectionView class.
<ContentPage></ContentPage>
as shown below.
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> |
IncrementalLoading.xaml
node and open IncrementalLoading
.xaml.cs
to open the C# code behind.
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(); } } } |