Прокрутка вниз в ListView с использованием события ItemAppearing пропускает записи в Xamarin.Forms

У меня есть ListView на странице Xamarin. Я использую событие ItemAppearing для прокрутки вниз. Высота ListViewCell большая, поэтому 1 экран покрывает первую и 80% часть второй ячейки просмотра.

Шаги для загрузки дополнительных данных для прокрутки вниз:

  1. Первоначально при загрузке страницы она вызывает API и получает 10 записей в списке EmployerResult. Это будет добавлено в ListView с помощью привязки данных.
  2. Событие ItemAppearing. В этом событии есть условие. Когда начнет появляться последняя ячейка, она вызовет API и снова добавит 10 записей в объект List ViewModel.
  3. Таким образом, он будет вызывать API и добавлять 10 записей каждый раз, когда начнет появляться последняя ячейка.

Теперь точка при каждой загрузке, она пропускает последнюю запись и показывает первую запись из следующих 10 записей. Однако иногда он пропускает 2-3 записи, если пользователь быстро прокручивает страницу вниз.

то есть, если у меня есть 10 записей в первый раз. Теперь я нахожусь на 9-й записи и прокручиваю вниз до 10. Начинает появляться 10-я запись, и срабатывает вызов API. После завершения этого вызова на экране появится 11-я запись в верхней части экрана. Здесь пропущена 10-я запись. Таким образом, пользователь увидит 11-ю запись, а не 10-ю. Здесь пользователю нужно снова прокрутить вверх, чтобы увидеть 10-ю запись.

Иногда он пропускает 2-3 записи, если пользователь быстро прокручивает страницу вниз.

Кто-нибудь может предложить мне?

Код

XAML

<ListView Grid.Row="0" x:Name="EmployerResultsListView"
          ItemsSource="{Binding EmployerResults}"
          HasUnevenRows = "true"
          SeparatorVisibility="None"
          IsPullToRefreshEnabled="true"
          RefreshCommand="{Binding RefreshCommand}"
          IsRefreshing="{Binding IsRefreshing, Mode=OneWay}"
          ItemAppearing="Handle_ItemAppearing"
          ItemTapped="OnEmployerResultsListViewItemTapped">
    <ListView.ItemTemplate>
        <DataTemplate>
            <local:EmployerResultViewCell />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

XAML.CS

private void Handle_ItemAppearing(object sender, ItemVisibilityEventArgs e)
{
    var itemTypeObject = e.Item as EmployerProfile;
    if (_viewModel.EmployerResults.Last() == itemTypeObject && _viewModel.EmployerResults.Count() != 1)
    {
        if (_viewModel.LoadMoreCommand.CanExecute(null))
        {
            _viewModel.LoadMoreCommand.Execute(null);
        }
    }
}

ViewModel

public EmployerResultsViewModel()
{
    LoadMoreCommand = new RelayCommand(LoadMoreEmployerResult, () => !IsBusy);
    EmployerResults = new ObservableRangeCollection<EmployerProfile>();
}
public ObservableRangeCollection<EmployerProfile> EmployerResults { get; set; }

private async void LoadMoreEmployerResult()
{
    IsBusy = true;
    EmployerResults.AddRange((await _employerApiClient.GetMoreData(pagenumber)));
    IsBusy = false;
}

person Nanji Mange    schedule 22.05.2018    source источник
comment
Ваш вопрос - это решение, которое я ищу.   -  person Ashi    schedule 02.12.2020
comment
Блестящая идея, но вызывающая много нестабильной прокрутки и мерцания на iOS   -  person Ashi    schedule 02.12.2020
comment
@Ashi Это работало правильно еще в 2018 году, когда я это реализовал.   -  person Nanji Mange    schedule 03.12.2020


Ответы (2)


Насколько я понимаю, вы пытаетесь выполнить ленивую загрузку.

- Во-первых, вы должны установить стратегию повторного использования следующим образом: CachingStrategy="RecycleElement", если вы хотите получить приемлемую производительность, как описано здесь https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/listview/performance, затем повторно проверить поведение события ItemAppearing.

- Тогда может быть хорошей идеей использовать или проанализировать существующий компонент, который отвечает вашим потребностям. Например: http://15mgm15.ghost.io/2017/11/28/implement-an-infinite-scrolling-listview-with-xamarin-forms/

person Rudy Spano    schedule 22.05.2018

Что я сделал, так это добавил дополнительную пустую ячейку в конце на LoadMoreEmployerResult и призвал загрузить больше, чтобы появиться на ней. При загрузке я удаляю эту пустую ячейку. Я чувствую, что это единственный способ решить мою проблему.

private async void LoadMoreEmployerResult()
{
    IsBusy = true;
    if(EmployerResults.Last().Name == "")
        EmployerResults.RemoveAt(EmployerResults.Count - 1);
    List<EmployerProfile> currentPageList= await _employerApiClient.GetMoreData(pagenumber);
    if(currentPageList.Count > 0)
    {
        EmployerResults.AddRange(currentPageList);
        EmployerResults.Add(new EmployerProfile());
    }

    IsBusy = false;
}
person Nanji Mange    schedule 18.06.2018