Easy ListView With “Load more” in xamarin forms





1.00/5 (1 vote)
With the increased amount of data a lazy loading mechanism is required in this article, we will explain how to build a lazy loaded list view easily.
Modern mobile applications are mostly data driven apps that depend heavily on listview’s. With the increased amount of data a lazy loading mechanism is required in this article, we will explain how to build a lazy loaded list view easily.

As an example I will build a last fm app that return a list of albums for an artist.
I started by creating a new xamarin app and then install the following nuget packages
Now let's create our view model
public class MainPageViewModel { private LastfmClient _client; public MainPageViewModel() { _client = new LastfmClient("b471c30029ba983849723e5120e7504c", "24c4739698eebb92f792b118095dbdff"); Artists = GetArtists().ToStandardIIncrementelLoadingCollection(10); } public IIncrementelLoadingCollection<AlbumModel> Artists { get; } private IAsyncEnumerable<AlbumModel> GetArtists() { return AsyncEnumerableBuilder.FromPaged((i, i1) => _client.Artist.GetTopTracksAsync("Britney Spears", true, i, i1), tracks => tracks.Select(t => new AlbumModel() { Name = t.Name, Id = t.Id, Image = t.Images.Large.ToString(), Duration = t.Duration }), (i, tracks) => tracks.TotalItems > i, (tracks, i) => tracks.Count() + i, tracks => { var pagenumber = (tracks?.Page ?? 0) + 1; return pagenumber; }, tracks => 20); } } }
The method AsyncEnumerableBuilder.FromPaged
was described in detail in my previous article "Mobile paged requests using IAsyncEnumerable" as a fast summary it allow building an IAsyncEnumerable
from a method that return paged results which is "GetTopTracksAsync
" in our case .
The method ToStandardIIncrementelLoadingCollection
allow the conversation from IAsyncEnumerable
to a bindable incremental collection that expose this interface
public interface IIncrementelLoadingCollection<T> : ICollection<T>, IEnumerable<T>, IEnumerable { ICommand LoadMoreCommand { get; } bool IsBusy { get; } }
The integer parameter is the number of items that will get loaded every time the user tap on load more , in our example it is 10 "ToStandardIIncrementelLoadingCollection(10)
"
Now finally the view
<StackLayout BindingContext="{Binding Path=Artists}"> <xForms:SfListView x:Name="listView" ItemSpacing="10" LoadMoreOption="Manual" LoadMoreCommand="{Binding LoadMoreCommand }" IsBusy="{Binding IsBusy}" ItemsSource="{Binding }"> <xForms:SfListView.ItemTemplate> <DataTemplate> <ViewCell> <StackLayout Orientation="Horizontal" Spacing="10"> <Image Source="{Binding Image}" HeightRequest="100" WidthRequest="100" /> <Label Text="{Binding Name}" /> </StackLayout> </ViewCell> </DataTemplate> </xForms:SfListView.ItemTemplate> <xForms:SfListView.LoadMoreTemplate> <DataTemplate> <Grid> <Label Text="Load More Items" TextColor="Black" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" IsVisible="{Binding IsBusy, Converter={StaticResource inverseBoolConverter}, Source={x:Reference Name=listView}}" /> <xForms:LoadMoreIndicator IsRunning="{Binding IsBusy, Source={x:Reference Name=listView}}" IsVisible="{Binding IsBusy, Source={x:Reference Name=listView}}" Color="Red" VerticalOptions="Center"/> </Grid> </DataTemplate> </xForms:SfListView.LoadMoreTemplate> </xForms:SfListView> </StackLayout>
The core part is
<StackLayout BindingContext="{Binding Path=Artists}"> <xForms:SfListView x:Name="listView" ItemSpacing="10" LoadMoreOption="Manual" LoadMoreCommand="{Binding LoadMoreCommand }" IsBusy="{Binding IsBusy}" ItemsSource="{Binding }">
we set the binding context of the listview to Artists which is our IIncrementelLoadingCollection
, the LoadMoreCommand
to the Artist.LoadMoreCommand
and IsBusy
to Artist.IsBusy
and finally the data source to the Artists itself.