.NET MAUI ListView Load on Demand
Loading a large data set on a mobile device has its challenges. One of the most popular approaches is using incremental data loading when the items need to be visualized. The ListView does this by using its load-on-demand functionality.
Configuration
The following properties control the LoadOnDemand
feature:
-
IsLoadOnDemandEnabled
(bool
)—Used to enable the load on demand mechanism of the ListView. -
IsLoadOnDemandActive
(bool
)—Used to control the loading indicator that is rendered when the data is retrieved asynchronously. Set it toTrue
when an async operation is running and items are loading. Set it toFalse
when the items are loaded. -
LoadOnDemandMode
—Used to set the loading mode. You can select between:-
Automatic
—The data is requested automatically when you scroll near the end of the ListView. -
Manual
—A button is rendered at the end of the ListView. The data is requested explicitly by pressing the button.
-
Methods to Load Data on Demand
Three options to load the data on demand, regardless of whether you use the Automatic
or Manual
loading mode:
-
Create a
ListViewLoadOnDemandCollection
instance as a source and pass it to the ListView Items Source property. -
Subscribe to the
LoadOnDemand
event and add the loaded data to the source. -
Use the
LoadOnDemand
User Command and add the loaded data to the source.
All three approaches for loading items on demand in the ListView work with both the automatic and manual
LoadOnDemandMode
.
Using LoadOnDemandCollection
To load items on demand, you can use the ListViewLoadOnDemandCollection
and set it as an ItemsSource
for the ListView. The ListViewLoadOnDemandCollection
accepts an action in the constructor and this action is later executed by the ListView in a non-UI thread when new items are requested.
The example below demonstrates how to use the LoadOnDemandCollection
:
1. Define a sample ViewModel
class with the Source
property of type ListViewLoadOnDemandCollection
:
public class ViewModel
{
public ListViewLoadOnDemandCollection Source { get; set; }
private int lodTriggerCount;
public ViewModel()
{
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 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));
}
}
}
2. Define the ListView instance and bind its ItemsSource
to the data in the ViewModel
:
<telerik:RadListView x:Name="listView"
IsLoadOnDemandEnabled="True"
ItemsSource="{Binding Source}"
LoadOnDemandMode="Automatic">
<telerik:RadListView.BindingContext>
<local:ViewModel />
</telerik:RadListView.BindingContext>
</telerik:RadListView>
3. Add the telerik
namespace:
xmlns:telerik="http://schemas.telerik.com/2022/xaml/maui"
For a runnable example with the ListView load-on-demand collection scenario, see the SDKBrowser Demo Application and go to the ListView > LoadOnDemand category.
Using LoadOnDemand Event
Another way to handle loading more items is to use the LoadOnDemand
event. This event is raised on a UI thread, so in the event handler you can add items right away or asynchronously:
- In case the data is available right away, add the items to the ListView
ItemsSource
in theLoadOnDemand
event handler. - If you require an async operation, set the
IsLoadOnDemandActive
property of the ListView toTrue
. This notifies the ListView that it must display the loading indicator. Then an async call can be initiated to get the data. When the new items are ready, you must set theIsLoadOnDemandActive
property toFalse
again to notify the ListView that the load-on-demand operation is completed.
The example below demonstrates how to use the LoadOnDemand event:
1. Define the ListView:
<telerik:RadListView x:Name="listView"
IsLoadOnDemandEnabled="True"
LoadOnDemand="ListView_LoadOnDemand"
LoadOnDemandMode="Automatic"/>
2. Set the ListView ItemsSource
, for example in the page constructor:
this.source = new ObservableCollection<string>();
for (int i = 0; i < 14; i++)
{
source.Add(string.Format("Item {0}", i));
}
this.listView.ItemsSource = this.source;
3. Add the following event handler:
private ObservableCollection<string> source;
private int lodCounter = 0;
private async void ListView_LoadOnDemand(object sender, EventArgs e)
{
// If you need to get new data asynchronously, you must manually update the loading status.
this.listView.IsLoadOnDemandActive = true;
IEnumerable<string> newItems = await this.GetNewItems();
foreach (string newItem in newItems)
{
this.source.Add(newItem);
}
this.listView.IsLoadOnDemandActive = false;
}
private async Task<IEnumerable<string>> GetNewItems()
{
this.lodCounter++;
await Task.Delay(4000); // Mimic getting data from server asynchronously.
return Enum.GetNames(typeof(DayOfWeek)).Select(day => string.Format("LOD: {0} - {1}", this.lodCounter, day));
}
For a runnable example with the ListView load-on-demand event scenario, see the SDKBrowser Demo Application and go to the ListView > LoadOnDemand category.
Using LoadOnDemand Command
This approach is similar to using the LoadOnDemand event, but in this case, the load-on-demand is handled in the ViewModel
through the LoadOnDemandUserCommand
exposed by the ListView. In the Execute
method of the command, you can add items right away or asynchronously:
- If the data is available right away, add the items to the ListView
ItemsSource
in theLoadOnDemand
commandExecute
method. - If you require an async operation, set the
IsLoadOnDemandActive
property of the ListView toTrue
. This notifies the ListView that it must display the loading indicator. Then an async call can be initiated to get the data. When the new items are ready, you must set theIsLoadOnDemandActive
property toFalse
again to notify the ListView that the load-on-demand operation is completed. You can control the behavior ofIsLoadOnDemandActive
through a binding to a boolean property in theViewModel
class.
The example below demonstrates how to use the LoadOnDemand
command:
1. Create a ViewModel
class with a LoadItemsCommand
as well as the IsLoadingMoreItems
property:
public class ViewModel : NotifyPropertyChangedBase
{
private bool isLoadingMoreItems;
private int lodCounter = 0;
public ViewModel()
{
this.Source = new ObservableCollection<string>();
for (int i = 0; i < 14; i++)
{
this.Source.Add(string.Format("Item {0}", i));
}
this.LoadItemsCommand = new Command(this.LoadItemsCommandExecute);
}
public ObservableCollection<string> Source { get; }
public ICommand LoadItemsCommand { get; set; }
public bool IsLoadingMoreItems
{
get { return this.isLoadingMoreItems; }
set { this.UpdateValue(ref this.isLoadingMoreItems, value); }
}
private async void LoadItemsCommandExecute(object obj)
{
// If you need to get new data asynchronously, you must manually update the loading status.
this.IsLoadingMoreItems = true;
IEnumerable<string> newItems = await this.GetNewItems();
foreach (string newItem in newItems)
{
this.Source.Add(newItem);
}
this.IsLoadingMoreItems = false;
}
private async Task<IEnumerable<string>> GetNewItems()
{
this.lodCounter++;
await Task.Delay(4000); // Mimic getting data from server asynchronously.
return Enum.GetNames(typeof(DayOfWeek)).Select(day => string.Format("LOD: {0} - {1}", this.lodCounter, day));
}
}
2. Define the RadListView
instance in XAML with the ListViewUserCommand
defined as well as the IsLoadOnDemandActive
property bound to the boolean property in the ViewModel
:
<telerik:RadListView x:Name="listView"
ItemsSource="{Binding Source}"
IsLoadOnDemandEnabled="True"
IsLoadOnDemandActive="{Binding IsLoadingMoreItems}"
LoadOnDemandMode="Manual">
<telerik:RadListView.BindingContext>
<local:ViewModel/>
</telerik:RadListView.BindingContext>
<telerik:RadListView.Commands>
<telerik:ListViewUserCommand Id="LoadOnDemand"
Command="{Binding LoadItemsCommand}" />
</telerik:RadListView.Commands>
</telerik:RadListView>
3. Add the telerik
namespaces:
xmlns:telerik="http://schemas.telerik.com/2022/xaml/maui"
For a runnable example with the ListView load-on-demand command scenario, see the SDKBrowser Demo Application and go to the ListView > LoadOnDemand category.
Advanced Options
You can also use the ListView options for performing advanced control over its load-on-demand feature.
Control the Number of Pre-loaded Items
This feature works in conjunction with the LoadOnDemandMode.Automatic mode of the ListView. You can control the minimum number of items loaded ahead through ListView LoadOnDemandBufferItemsCount
property. By default, the property is for 10 items. When ListView requests an item in the buffer, it will trigger a new loading batch.
Change the Appearance of the Manual Load Button
This feature works in conjunction with the LoadOnDemandMode.Manual mode of the ListView. You can control the content of the Load More Button through the LoadOnDemandItemTemplate
property.
<telerik:RadListView.LoadOnDemandItemTemplate>
<DataTemplate>
<Grid BackgroundColor="Red">
<Label FontSize="24"
HorizontalOptions="Center"
Text="Load more items"
TextColor="Black" />
</Grid>
</DataTemplate>
</telerik:RadListView.LoadOnDemandItemTemplate>
For a runnable example with the ListView load-on-demand manual button customization scenario, see the SDKBrowser Demo Application and go to the ListView > LoadOnDemand category.
Change the Appearance of the Manual Loading Indicator
This feature works in conjunction with the LoadOnDemandMode.Manual mode of the ListView.
You can control the content of the Loading Indicator through the LoadingOnDemandItemTemplate
property.
<telerik:RadListView.LoadingOnDemandItemTemplate>
<DataTemplate>
<Grid BackgroundColor="Green">
<Label FontSize="24"
HorizontalOptions="Center"
Text="Loading..."
TextColor="White" />
</Grid>
</DataTemplate>
</telerik:RadListView.LoadingOnDemandItemTemplate>
For a runnable example with the ListView load-on-demand manual loading indicator, see the SDKBrowser Demo Application and go to the ListView > LoadOnDemand category.