Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WP 8.1 ISupportIncrementalLoading LoadMoreItemsAsync keeps getting called endlessly

I am trying to implement infinite scrolling using the following example

http://www.davidbritch.com/2014/05/data-virtualisation-using.html

The problem is that in my case LoadMoreItemsAsync keeps getting called endlessly. I am developing this on a hub (not sure if this makes a difference) and using MVVMLight. Given below is my code

.xaml

<Page
x:Class="MyFileServer.UniversalApp.AppHubPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyFileServer.UniversalApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
DataContext="{Binding Source={StaticResource MFSViewModelLocator}, Path=AppHub}">

<Grid>
    <Hub Header="My File Server">
        <HubSection x:Name="MFSNotifications" Header="Notifications">
            <DataTemplate>
                <StackPanel>
                    <ListView x:Name="Notifications"  ItemsSource="{Binding IncrementalNotifications}" >
                        <ListView.ItemTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding NotificationDescription}"/>
                            </DataTemplate>
                        </ListView.ItemTemplate>
                    </ListView>
                </StackPanel>
            </DataTemplate>
        </HubSection>
        <HubSection x:Name="MFSFiles" Header="Files"></HubSection>
    </Hub>
</Grid>

Given below is my implementation of ISupportIncrementalLoading

public class IncrementalLoadingNotificationsCollection : ObservableCollection<MFSNotificationModel>, ISupportIncrementalLoading
{
    private INotificationService _notificationService;
    public IncrementalLoadingNotificationsCollection(INotificationService notificationService)
    {
        HasMoreItems = true;
        _notificationService = notificationService;
    }


    public bool HasMoreItems
    {
        get;
        private set;
    }

    public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
    {
        return InnerLoadMoreItemsAsync(count).AsAsyncOperation();
    }

    private async Task<LoadMoreItemsResult> InnerLoadMoreItemsAsync(uint expectedCount)
    {
        var actualCount = 0;
        IList<MFSNotificationModel> notifications;

        try
        {
            notifications = await _notificationService.GetNotificationsAsync(ConfigurationSettings.AccessToken, 8);
        }
        catch (Exception)
        {
            HasMoreItems = false;
            throw;
        }

        if (notifications != null && notifications.Any())
        {
            foreach (var notification in notifications)
            {
                Add(notification);
            }

            actualCount += notifications.Count;
            //_photoStartIndex += (uint)actualCount;
        }
        else
        {
            HasMoreItems = false;
        }

        return new LoadMoreItemsResult
        {
            Count = (uint)actualCount
        };
    }
}

Given below is the extract from the viewmodel

public IncrementalLoadingNotificationsCollection IncrementalNotifications
{
    get
    {
        return _incrementalNotifications;
    }
    set
    {
        _incrementalNotifications = value;                
        if (!Equals(null) && _incrementalNotifications.Count > 0)
        {
            DispatcherHelper.CheckBeginInvokeOnUI(() =>
            {
                RaisePropertyChanged(() => IncrementalNotifications);
            });
        }
    }
}

Any help to solve this is much appreciated.

like image 334
user3547774 Avatar asked Jan 10 '23 20:01

user3547774


2 Answers

As you mentioned in your answer, the StackPanel was the culprit. The StackPanel control won't constrain the size of its content. This means as your ListView loads more items, the height of the ListView will also grow inside the StackPanel, and so the ListView thinks that every item is visible, so it loads more items, and so on.

This also affects virtualization too, which is another reason why you should never put a ListView inside a StackPanel. According to the docs:

When the size of the ItemsControl's viewport isn't restricted, the control doesn't perform virtualization. Instead, it creates an item container for each item in its collection. Some common containers that don't restrict the viewport size are Canvas, StackPanel, and ScrollViewer. You can enable virtualization in this situation by setting the size of ItemsControl directly, instead of letting it be sized by its parent container.

So your options are:

  • Don't use a StackPanel container. Use a Grid instead.
  • If you want to use a StackPanel container then you must manually set the size (height) of the ListView.
like image 79
Decade Moon Avatar answered Jan 25 '23 12:01

Decade Moon


After playing around I managed to solve this. The problem was the StackPanel in which the ListView was in. I dont know why but for some reason the existence of the StackPanel caused the LoadMoreItemsAsync getting called endlessly and as soon as I removed it, it worked fine.

like image 38
user3547774 Avatar answered Jan 25 '23 12:01

user3547774