Xamarin bug-ish behaviour in CarouselView - CurrentItemChanged event fired unexpectedly?

心不动则不痛 提交于 2021-01-07 00:59:25

问题


While I was trying to implement an infinite scroll page I've encountered a strange behaviour with the CurrentItemChanged event of Xamarin.Forms.CarouselView.

While the user scrolls, new items are added to the ItemSource and old items are removed (for low memory consumption).

After I encountered the strange behaviour I've debugged and narrowed down the problem.

So here are the steps to replicate the situation.

  • Create a CarouselView.
  • Create a ObservableCollection<T> in the code behind and assign it to the ItemSource.
  • Create a method and subscribe it to the CurrentItemChanged event of the CarouselView. This method must at some point remove an element from the ItemSource that has an index between 0 and the index of the CurrentItem.
  • Now deploy the app and swipe the CarouselView once. This will result in an endless loop of scrolls that will keep going untill all of the items are removed from the ItemSource.

The method from step 3 must look like below.

bool FirstTime = true;
private void StateChanged(object s, EventArgs e)
{
    // Pass the first call which is made right after the Carousel is initialized.
    if (FirstTime) { FirstTime = false; return; }

    var currentItem = (Model)Carousel.CurrentItem; // For debug.
    var index = Models.IndexOf(currentItem); // Same.

    // Step 3's requirement
    Models.RemoveAt(0);
}

When you instead for example add a button to the page and assign the method you've created at the step 3 to it's Clicked event, and continue with the 4th step and manually press button after each scroll the endless loop won't occur.


I don't know if this is a feature or a bug but this certainly was unexpected, at least for me. I would love to figure out how to overcome this problem and learn why it works like this.

Note: I'm aware that removing the current item will cause such problem but the described behaviour occurs either ways. Also CarouselView.CurrentItem is updated before the CurrentItemChanged event is fired.


回答1:


This will result in an endless loop of scrolls that will keep going untill all of the items are removed from the ItemSource.

This is because ObservableCollection has CollectionChanged event which will be called when the data collection is changed. When you remove the first item, the index is refershed and the event will also be triggered.

For this function, you could detect if the current item is the last one to update the data collection. Check the code:

public partial class Page1 : ContentPage
{
    CustomViewModel viewModel = new CustomViewModel();
    ObservableCollection<CustomModel> collection;
    public Page1()
    {
        InitializeComponent();

        BindingContext = viewModel;
        collection = viewmodel.DataCollection;
    }

    private void CarouselView_CurrentItemChanged(object sender, CurrentItemChangedEventArgs e)
    {
        var item = e.CurrentItem as CustomModel;
        var index = collection.IndexOf(item);

        if (collection.Count == (index + 1))
        {
            collection.RemoveAt(0);
            collection.Add(new CustomModel { ... });
        }
    }
}


来源:https://stackoverflow.com/questions/65106771/xamarin-bug-ish-behaviour-in-carouselview-currentitemchanged-event-fired-unexp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!