I see no event representing this occurrence - All of the items in the RadListView are visually built and ready for user interaction.
I have a wait spinner I display when a control is not ready for user interaction or when a screen is being built. I can easily make a change to a RadListView's ItemSource, but it takes a bit for the display to be properly built. Without an event the represents the finishing of the display, I have no known spot at which I can turn off my wait spinner.
I'm open to any and all ideas. Additionally, consider this an enhancement request for just such an event.
4 Answers, 1 is accepted
The RadListView uses UI Virtualization. It will render some items above and below the view port, but not all of the items. They'll be rendered as they're needed.
Therefore, you can turn off your busy indicator once the data is loaded into the collection you have bound to the ItemsSource.
Examples
In the XAML, I have a RadListView and a RadBusyIndicator:
<
ContentPage.BindingContext
>
<
portable:ViewModel
/>
</
ContentPage.BindingContext
>
<
Grid
>
<
telerikDataControls:RadListView
x:Name
=
"listView"
ItemsSource
=
"{Binding Source}"
>
<
telerikDataControls:RadListView.ItemTemplate
>
<
DataTemplate
>
<
listView:ListViewTextCell
Text
=
"{Binding Name}"
/>
</
DataTemplate
>
</
telerikDataControls:RadListView.ItemTemplate
>
</
telerikDataControls:RadListView
>
<
YourBusySpinner
IsVisible-OR-IsBusy
=
"{Binding IsBusy}"
/>
</
Grid
>
And in the ViewModel, notice I toggle the IsBusy property on and off around the data loading:
public
class
ViewModel : NotifyPropertyChangedBase
{
private
ObservableCollection<SourceItem> source;
private
bool
isBusy;
public
ViewModel()
{
}
public
ObservableCollection<SourceItem> Source => source ?? (source =
new
ObservableCollection<SourceItem>());
public
bool
IsBusy
{
get
=> isBusy;
set
{ isBusy = value; OnPropertyChanged();}
}
public
void
LoadItems()
{
IsBusy =
true
;
for
(
int
i = 0; i < 30; i++)
{
Task.Delay(100);
Source.Add(
new
SourceItem($
"Item {i}"
));
}
IsBusy =
false
;
}
}
Alternative - LoadOnDemand
Alternatively, if you're using incremental data calls, you can use the built-in LoadOnDemand features and only show the spinner when the ListView is fetching the next set of items.
I've attached a demo that shows how to do this with automatic LoadOnDemand, here's the method that gets the items whenever the user scrolls down:
private
IEnumerable<
object
> GetMoreItems(CancellationToken cancelationToken)
{
List<
string
> result =
new
List<
string
>();
try
{
Device.BeginInvokeOnMainThread(() =>
{
IsBusy =
true
;
});
//simulate 2 second delay
Task.Delay(2000, cancelationToken).Wait(cancelationToken);
lodTriggerCount++;
foreach
(
string
item
in
Enum.GetNames(
typeof
(DayOfWeek)))
result.Add($
"LOD: {lodTriggerCount} - {item}"
);
return
result;
}
catch
(Exception ex)
{
return
null
;
}
finally
{
Device.BeginInvokeOnMainThread(() =>
{
IsBusy =
false
;
});
}
}
Take a look at the demo, find all the code on StartPage.xaml and StartPage.xaml.cs. When you run it, scroll down after the first set of items load.
Wrapping Up
If you have any further questions, please open a support ticket here so that you can share your code and we can investigate further.
Regards,
Lance | Tech Support Engineer, Sr.
Progress Telerik

As always, thanks for looking into it and for your reply, Lance.
Your suggestion works just fine and dandy, but for one small problem - I'm binding my ItemSource, not setting it programmatically. I can, and will, switch to setting it programmatically if that's my only option for now, but I will nonetheless suggest that an event that represents "Items are Completely Loaded and Displayed" be added.
If this is my only option for now, just let me know and I'll mark this thread as answered.
Both of my examples are using data binding, the C# you see is in the pasted code is the View Model. In the attached runnable demo, it uses data binding and automatic load on demand.
In any of these cases, your approach will be the same: monitor the loading of the data, as opposed to watching the RadListView for cues to when the data is done.
1 - Have a boolean property "IsBusy" (or similar) in your ViewModel
2 - In the view, bind your spinner to the IsBusy property
2 - Trip the IsBusy flag to true before fetching your data
3 - Trip the IsBusy flag to false when it's done.
I hope this was helpful, let me know if you have any additional questions.
Regards,
Lance | Tech Support Engineer, Sr.
Progress Telerik

My apologies; I read too quickly.
Thanks for your help.