Click here to Skip to main content
14,299,664 members

Easy ListView With “Load more” in xamarin forms

Rate this:
0.00 (No votes)
Please Sign up or sign in to vote.
0.00 (No votes)
6 Sep 2019CPOL
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.

Image 1

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

  1. Inflatable.Lastfm
  2. Syncfusion.Xamarin.SfListView
  3. AsyncEnumerableExtensions.Standard

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

DotnetShtien
Austria Austria
I am a software engineer at PlanRadar currently living in Vienna, Austria. My interests range from technology to web development. I am also interested in programming, xamarin, and mobile development.

Comments and Discussions

 
-- There are no messages in this forum --
Technical Blog
Posted 25 Aug 2019

Tagged as

Stats

1.6K views
2 bookmarked