CarouselView 中的 Xamarin 错误行为 - CurrentItemChanged 事件意外触发? [英] Xamarin bug-ish behaviour in CarouselView - CurrentItemChanged event fired unexpectedly?
问题描述
当我尝试实现无限滚动页面时,我遇到了 Xamarin.Forms.CarouselView
的 CurrentItemChanged
事件的奇怪行为.
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
. - 创建一个方法并将其订阅到
CarouselView
的CurrentItemChanged
事件.此方法必须在某个时候从ItemSource
中删除一个元素,该元素的索引介于0
和CurrentItem
的索引之间. - 现在部署应用程序并滑动
CarouselView
一次.这将导致无限循环滚动,直到所有项目从ItemSource
中删除.
- Create a
CarouselView
. - Create a
ObservableCollection<T>
in the code behind and assign it to theItemSource
. - Create a method and subscribe it to the
CurrentItemChanged
event of theCarouselView
. This method must at some point remove an element from theItemSource
that has an index between0
and the index of theCurrentItem
. - 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 theItemSource
.
步骤 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.CurrentItem
在 CurrentItemChanged
事件触发之前更新.
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屋!