This is a migrated thread and some comments may be shown as answers.

Load on demand query

4 Answers 206 Views
ListView
This is a migrated thread and some comments may be shown as answers.
vivek
Top achievements
Rank 1
vivek asked on 24 Nov 2017, 02:07 PM

We are getting the item source of our list from an API. The API is created in such a way that it returns 25 records in  1st time. If we want the next 25 records we need to hit the API again. 

What do you propose how can we use LoadonDemand property:

I can see two different type:

1.Subscribe to LoadOnDemand event and add the loaded data to the source.
2. Create ListViewLoadOnDemandCollection instance as source and pass it to listview ItemsSource property

to get the next 25 records when user scrolls to last item of list. The API might take sufficient time to return the response.

 

 

 

4 Answers, 1 is accepted

Sort by
0
Lance | Manager Technical Support
Telerik team
answered on 24 Nov 2017, 04:42 PM
Hello Vivek,

You're correct, those are the two options. Either one will work for you, the option to use is up to you and how your application is being built.

The event approach is good if you're doing your work mostly in the code-behind. However, if you're using MVVM, I recommend the ListViewLoadOnDemandCollection, so you can do the work in the view model. The ListViewLoadOnDemandCollection and the RadListView work together closely to provide a smooth fetch/busy/result experience. 

This section in the documentation shows how to use the ListViewLoadOnDemandCollection.


Paging

Note that the RadListView will not automatically handle paging, you'll need to know how your API handles paging/item count and track that in the view model so you know what to send the API when the next set of items are needed.

Most APIs return a page number with a set of items, for example:

root:
{
    page: 1,
    items: []
}

However, if it doesn't, you'll need to keep track yourself.

For an example of keeping track of how many time the fetch method is used, see the following line in the documentation's code example:

this.lodTriggerCount++;


Fetch Time

The RadListView will show a busy indicator will show a busy indicator while the fetch is occurring. If you look at the documentation's code example, you'll see that we have in there to simulate a 4 second fetch time.

Task.Delay(4000, cancelationToken).Wait();


Demos

You can find demos of this in action on your PC in the SDKBrowser examples. Find the solution at the following location: C:\Program Files (x86)\Progress\Telerik UI for Xamarin R3 2017\Examples\XamarinForms\SDKBrowser.sln

After you open the solution, drill down to the following project folder for the specific examples: SDKBrowser (PCL project) > Examples > ListView > LoadOnDemand folder for the examples.


We try to provide you with flexible options: Manual, Automatic and Event or Collection, but ultimately it's up to you to choose the one that makes the most sense for your project and API.

I hope this information helps. 

Regards,
Lance | Tech Support Engineer, Sr.
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
vivek
Top achievements
Rank 1
answered on 24 Nov 2017, 06:45 PM

Thanx for such great response.

I am using MVVM , so it would be good if we use ListViewLoadOnDemandCollection instance as source and pass it to listview ItemsSource property. i am confused in one thing only where should i call my first and next successive time when i want to fetch next record. lets take the below code as an reference.

public class ListViewModel
{
    public ListViewLoadOnDemandCollection Source { get; set; }
    private int lodTriggerCount;
    public ListViewModel()
    {
        this.Source = new ListViewLoadOnDemandCollection((cancelationToken) =>
        {
            List<string> result = new List<string>();
 
            try
            {
                //simulates connection latency
                Task.Delay(4000, cancelationToken).Wait();
 
                this.lodTriggerCount++;
                foreach (string item in Enum.GetNames(typeof(DayOfWeek)))
                {
                    result.Add(string.Format("LOD: {0} - {1}", lodTriggerCount, item));
                }
                return result;
            }
            catch (Exception ex)
            {
                //exception is thrown when the task is canceled. Returning null does not affect the ItemsSource.
                return null;
            }
        });
 
        for (int i = 0; i < 14; i++)
        {
            Source.Add(string.Format("Item {0}", i));
        }
    }
}
0
vivek
Top achievements
Rank 1
answered on 24 Nov 2017, 06:48 PM
Thanx for such great response.
I am using MVVM , so it would be good if we use
public class ListViewModel
{
    public ListViewLoadOnDemandCollection Source { get; set; }
    private int lodTriggerCount;
    public ListViewModel()
    {
        this.Source = new ListViewLoadOnDemandCollection((cancelationToken) =>
        {
            List<string> result = new List<string>();
 
            try
            {
                //simulates connection latency
                Task.Delay(4000, cancelationToken).Wait();
 
                this.lodTriggerCount++;
                foreach (string item in Enum.GetNames(typeof(DayOfWeek)))
                {
                    result.Add(string.Format("LOD: {0} - {1}", lodTriggerCount, item));
                }
                return result;
            }
            catch (Exception ex)
            {
                //exception is thrown when the task is canceled. Returning null does not affect the ItemsSource.
                return null;
            }
        });
 
        for (int i = 0; i < 14; i++)
        {
            Source.Add(string.Format("Item {0}", i));
        }
    }
}
 i am confused in one thing only where should i call my API first and then next successive time when i want to fetch next record. lets take the abovecode as an reference.
0
Accepted
Lance | Manager Technical Support
Telerik team
answered on 24 Nov 2017, 08:21 PM
Hi Vivek,

You return your items in the action (see comment below) and this action is used for every call.

this.Source = new ListViewLoadOnDemandCollection((cancelationToken) =>
{
    List<string> result = new List<string>();
  
    try
    {
        //Get your data here and return the items that are to be added to the RadListView
        return result;
    }
    catch (Exception ex)
    {
        return null;
    }
});


The collection takes an Action of type Func<CancellationToken, IEnumerable<object>> in the constructor, so if you prefer you could use a named method if you prefer:

public ViewModel()
{
    Source = new ListViewLoadOnDemandCollection(GetMyData);
}
 
private IEnumerable<object> GetMyData(CancellationToken ctk)
{
    // get and return your items here
    return itemsToAddToTheCollection;
}


As far as keeping track of what page to get, it depends on your API. Some APIs use an offset, others use a page number. Just have a variable in the view model that holds the value of the offset/page you're currently on and use that value for the next call.

Regards,
Lance | Tech Support Engineer, Sr.
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Tags
ListView
Asked by
vivek
Top achievements
Rank 1
Answers by
Lance | Manager Technical Support
Telerik team
vivek
Top achievements
Rank 1
Share this question
or