Reputation: 1131
I'm writing an UWP app in C#. I have a page with a ListView taking all space available.
The list of items is huge so I use IncrementalLoadingCollection
to load items gradually in the ListView while user is scrolling.
The problem is when I start the app all items are loaded right away in the ListView. GetPagedItemsAsync
is called over and over and the app crashes throwing Layout cycle detected
.
The only way I get the scroll loading to work is by fixing the ListView or height to a certain value. With fixed height on the ListView GetPagedItemsAsync
is only called once at initialization and the scroll loading works as expected.
The thing is I want the ListView to fill page content so I don't want to set height to a specific value.
Page content
<Grid
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<ListView
x:Name="channelList"
ItemsSource="{x:Bind Channels}"
DataFetchSize="100"
IncrementalLoadingTrigger="Edge"
IncrementalLoadingThreshold="5"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
Page class
public sealed partial class ChannelsPage : Page
{
private IncrementalLoadingCollection<ChannelSource, ChannelModel> Channels { get; set; }
public ChannelsPage()
{
this.InitializeComponent();
Channels = new IncrementalLoadingCollection<ChannelSource, ChannelModel>();
}
private class ChannelSource : IIncrementalSource<ChannelModel>
{
private int Current { get; set; } = 0;
private int Limit { get; set; } = 100;
public async Task<IEnumerable<ChannelModel>> GetPagedItemsAsync(int pageIndex, int pageSize, CancellationToken cancellationToken = default(CancellationToken))
{
List<ChannelModel> channels = ChannelModel.List(false, Limit, Current);
Current += Limit;
return channels;
}
}
}
[Solved]
The ListView
was expanding out of bound due to a parent ScrollViewer
in another file. Because of this continuous expansion out of its parent the items was loading non-stop.
Upvotes: 1
Views: 1189
Reputation: 39082
The key to unlocking this mystery is the IncrementalLoadingThreshold
. In simple terms it says the system how many "pages" of content to preload. In case you use 5, the system will make sure to have 5 times the height of the control ready to view. Try decreasing the value to 1 and you should see the method will be called once or twice. Even lower values like 0.1 are also possible.
Secondly, ensure you do not put the ListView
into any layout control which allows it to expand beyond any bounds. For example, putting the list in a Grid.Row
which has RowDefinition
of Height="*"
will make the list as long as it needs - which means it will keep loading items until there are no more available.
Finally, you need to make sure to indicate when you are out of items. This is easy if you return an empty IEnumerable
from the method.
Upvotes: 3