CarouselView 中的 Xamarin 错误行为 - CurrentItemChanged 事件意外触发? [英] Xamarin bug-ish behaviour in CarouselView - CurrentItemChanged event fired unexpectedly?

查看:28
本文介绍了CarouselView 中的 Xamarin 错误行为 - CurrentItemChanged 事件意外触发?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我尝试实现无限滚动页面时,我遇到了 Xamarin.Forms.CarouselViewCurrentItemChanged 事件的奇怪行为.

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

当用户滚动时,新项目被添加到 ItemSource 并删除旧项目(为了低内存消耗).

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.

  • 创建一个CarouselView.
  • 在后面的代码中创建一个ObservableCollection,并赋值给ItemSource.
  • 创建一个方法并将其订阅到 CarouselViewCurrentItemChanged 事件.此方法必须在某个时候从 ItemSource 中删除一个元素,该元素的索引介于 0CurrentItem 的索引之间.
  • 现在部署应用程序并滑动 CarouselView 一次.这将导致无限循环滚动,直到所有项目从 ItemSource 中删除.
  • 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.

步骤 3 中的方法必须如下所示.

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);
}

例如,当您向页面添加一个按钮并将您在第 3 步中创建的方法分配给它的 Clicked 事件时,然后继续第 4 步并在每个步骤之后手动按下按钮滚动不会发生无限循环.

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.

注意:我知道删除当前项目会导致此类问题,但所描述的行为会以任何一种方式发生.此外 CarouselView.CurrentItemCurrentItemChanged 事件触发之前更新.

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.

推荐答案

这将导致无限循环滚动,直到所有项目从 ItemSource 中删除.

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

这是因为 ObservableCollection 具有 CollectionChanged 事件,该事件将在数据集合更改时调用.当你移除第一项时,索引会被引用,事件也会被触发.

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 { ... });
        }
    }
}

这篇关于CarouselView 中的 Xamarin 错误行为 - CurrentItemChanged 事件意外触发?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆