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
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
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));
}
}
}
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));
}
}
}
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