Xamarin.forms: [Bug] [iOS] ObservableCollection.RemoveAt(index) with a valid index raises ArgementOutOfRangeException.

Created on 11 Apr 2020  路  8Comments  路  Source: xamarin/Xamarin.Forms

In latest XF version (4.5.0.617) using ObservableCollection.RemoveAt(index) with a valid index raises ArgementOutOfRangeException.
It is an iOS exception only. On Android that exact same code it is working fine.

The ObservableCollection is bound to the ItemsSourceof a CarouselViewand the ObservableCollection.RemoveAt(index) is executed in an event raised bij the Messenger-Service (not on the main thread). If the code is changed to:

var list = ObservableCollection.ToList();
list.RemoveAt(index)
ObservableCollection = new ObservableCollection(list)

The codes executes fine on iOS and without raising any Exception.
The index is valid. For example 5 in a collection count of 20.

carouselview 3 high in-progress iOS 馃崕 bug

Most helpful comment

Similar issues have been reported a few times now over the last 5 months without resolution. CollectionViews, and by the looks of this issue - CarouselViews, simply don't support offscreen ObservableCollection changes (add or delete). It was broken in December and I haven't seen any urgency in trying to fix it. I pity the poor developer potentially tasked with updating the VS template for a XF Shell based app to use the latest and greatest CollectionView instead of the old ListView.

All 8 comments

@goedware Can you please attach a small project that demonstrates this issue? Thanks!

Attached a sample project.

Start the app, swipe to an item in the CarouselView, press Delete button. A Modal Page opens. Press Close button and a message is send to delete the current item in the CarouselView. On Android that item is removed by ObservableCollection.RemoveAt(index). On iOS the application crashes with an exception (ArgementOutOfRangeException) on that same line of code.

Hope this helps.

ObservableCollectionTest.zip

This is the stacktrace:

Unhandled Exception:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
  at System.Collections.Generic.List`1[T].get_Item (System.Int32 index) [0x00009] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/Common/src/CoreLib/System/Collections/Generic/List.cs:161 
  at System.Collections.ObjectModel.Collection`1[T].System.Collections.IList.get_Item (System.Int32 index) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/Common/src/CoreLib/System/Collections/ObjectModel/Collection.cs:266 
  at Xamarin.Forms.Platform.iOS.ObservableItemsSource.ElementAt (System.Int32 index) [0x0000f] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ObservableItemsSource.cs:268 
  at Xamarin.Forms.Platform.iOS.ObservableItemsSource.get_Item (System.Int32 index) [0x00000] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ObservableItemsSource.cs:37 
  at Xamarin.Forms.Platform.iOS.ObservableItemsSource.GetIndexForItem (System.Object item) [0x00004] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ObservableItemsSource.cs:71 
  at Xamarin.Forms.Platform.iOS.CarouselViewController.CollectionItemsSourceChanged (System.Object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x0000c] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\CarouselViewController.cs:122 
  at Xamarin.Forms.Platform.iOS.ObservableItemsSource.CollectionChanged (System.Collections.Specialized.NotifyCollectionChangedEventArgs args) [0x00055] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ObservableItemsSource.cs:132 
  at Xamarin.Forms.Platform.iOS.ObservableItemsSource.CollectionChanged (System.Object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs args) [0x0002d] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ObservableItemsSource.cs:105 
  at System.Collections.ObjectModel.ObservableCollection`1[T].OnCollectionChanged (System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x00018] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/System.ObjectModel/src/System/Collections/ObjectModel/ObservableCollection.cs:263 
  at System.Collections.ObjectModel.ObservableCollection`1[T].OnCollectionChanged (System.Collections.Specialized.NotifyCollectionChangedAction action, System.Object item, System.Int32 index) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/System.ObjectModel/src/System/Collections/ObjectModel/ObservableCollection.cs:338 
  at System.Collections.ObjectModel.ObservableCollection`1[T].RemoveItem (System.Int32 index) [0x00021] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/System.ObjectModel/src/System/Collections/ObjectModel/ObservableCollection.cs:182 
  at System.Collections.ObjectModel.Collection`1[T].RemoveAt (System.Int32 index) [0x00027] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/Common/src/CoreLib/System/Collections/ObjectModel/Collection.cs:144 
  at ObservableCollectionTest.MainPage.Callback (Xamarin.Forms.Page page) [0x0001d] in /Users/jsuarez/Downloads/ObservableCollectionTest/ObservableCollectionTest/ObservableCollectionTest/MainPage.xaml.cs:40 
  at (wrapper managed-to-native) System.Reflection.RuntimeMethodInfo.InternalInvoke(System.Reflection.RuntimeMethodInfo,object,object[],System.Exception&)
  at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x0006a] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/mcs/class/corlib/System.Reflection/RuntimeMethodInfo.cs:395 
   --- End of inner exception stack trace ---
  at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00081] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/mcs/class/corlib/System.Reflection/RuntimeMethodInfo.cs:409 
  at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/Common/src/CoreLib/System/Reflection/MethodBase.cs:53 
  at Xamarin.Forms.MessagingCenter+Subscription.InvokeCallback (System.Object sender, System.Object args) [0x00064] in D:\a\1\s\Xamarin.Forms.Core\MessagingCenter.cs:94 
  at Xamarin.Forms.MessagingCenter.InnerSend (System.String message, System.Type senderType, System.Type argType, System.Object sender, System.Object args) [0x0006b] in D:\a\1\s\Xamarin.Forms.Core\MessagingCenter.cs:217 
  at Xamarin.Forms.MessagingCenter.Xamarin.Forms.IMessagingCenter.Send[TSender] (TSender sender, System.String message) [0x00013] in D:\a\1\s\Xamarin.Forms.Core\MessagingCenter.cs:127 
  at ObservableCollectionTest.ModalPage.OnCloseClicked (System.Object sender, System.EventArgs e) [0x0000d] in /Users/jsuarez/Downloads/ObservableCollectionTest/ObservableCollectionTest/ObservableCollectionTest/ModalPage.xaml.cs:19 
  at Xamarin.Forms.Button.Xamarin.Forms.Internals.IButtonElement.PropagateUpClicked () [0x00000] in D:\a\1\s\Xamarin.Forms.Core\Button.cs:185 
  at Xamarin.Forms.ButtonElement.ElementClicked (Xamarin.Forms.VisualElement visualElement, Xamarin.Forms.Internals.IButtonElement ButtonElementManager) [0x0001f] in D:\a\1\s\Xamarin.Forms.Core\ButtonElement.cs:61 
  at Xamarin.Forms.Button.SendClicked () [0x00000] in D:\a\1\s\Xamarin.Forms.Core\Button.cs:171 
  at Xamarin.Forms.Platform.iOS.ButtonElementManager.OnButtonTouchUpInside (Xamarin.Forms.IButtonController element) [0x00009] in D:\a\1\s\Xamarin.Forms.Platform.iOS\Renderers\ButtonElementManager.cs:86 
  at Xamarin.Forms.Platform.iOS.ButtonRenderer.OnButtonTouchUpInside (System.Object sender, System.EventArgs eventArgs) [0x00000] in D:\a\1\s\Xamarin.Forms.Platform.iOS\Renderers\ButtonRenderer.cs:147 
  at UIKit.UIControlEventProxy.Activated () [0x00004] in /Library/Frameworks/Xamarin.iOS.framework/Versions/13.16.0.13/src/Xamarin.iOS/UIKit/UIControl.cs:38 
--- End of stack trace from previous location where exception was thrown ---

  at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain(int,string[],intptr,intptr)
  at UIKit.UIApplication.Main (System.String[] args, System.IntPtr principal, System.IntPtr delegate) [0x00005] in /Library/Frameworks/Xamarin.iOS.framework/Versions/13.16.0.13/src/Xamarin.iOS/UIKit/UIApplication.cs:86 
  at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0000e] in /Library/Frameworks/Xamarin.iOS.framework/Versions/13.16.0.13/src/Xamarin.iOS/UIKit/UIApplication.cs:65 
  at ObservableCollectionTest.iOS.Application.Main (System.String[] args) [0x00001] in /Users/jsuarez/Downloads/ObservableCollectionTest/ObservableCollectionTest/ObservableCollectionTest.iOS/Main.cs:17
2020-04-21 09:38:40.066339+0200 ObservableCollectionTest.iOS[5961:215658] Unhandled managed exception: Exception has been thrown by the target of an invocation. (System.Reflection.TargetInvocationException)
  at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00081] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/mcs/class/corlib/System.Reflection/RuntimeMethodInfo.cs:409 
  at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/Common/src/CoreLib/System/Reflection/MethodBase.cs:53 
  at Xamarin.Forms.MessagingCenter+Subscription.InvokeCallback (System.Object sender, System.Object args) [0x00064] in D:\a\1\s\Xamarin.Forms.Core\MessagingCenter.cs:94 
  at Xamarin.Forms.MessagingCenter.InnerSend (System.String message, System.Type senderType, System.Type argType, System.Object sender, System.Object args) [0x0006b] in D:\a\1\s\Xamarin.Forms.Core\MessagingCenter.cs:217 
  at Xamarin.Forms.MessagingCenter.Xamarin.Forms.IMessagingCenter.Send[TSender] (TSender sender, System.String message) [0x00013] in D:\a\1\s\Xamarin.Forms.Core\MessagingCenter.cs:127 
  at ObservableCollectionTest.ModalPage.OnCloseClicked (System.Object sender, System.EventArgs e) [0x0000d] in /Users/jsuarez/Downloads/ObservableCollectionTest/ObservableCollectionTest/ObservableCollectionTest/ModalPage.xaml.cs:19 
  at Xamarin.Forms.Button.Xamarin.Forms.Internals.IButtonElement.PropagateUpClicked () [0x00000] in D:\a\1\s\Xamarin.Forms.Core\Button.cs:185 
  at Xamarin.Forms.ButtonElement.ElementClicked (Xamarin.Forms.VisualElement visualElement, Xamarin.Forms.Internals.IButtonElement ButtonElementManager) [0x0001f] in D:\a\1\s\Xamarin.Forms.Core\ButtonElement.cs:61 
  at Xamarin.Forms.Button.SendClicked () [0x00000] in D:\a\1\s\Xamarin.Forms.Core\Button.cs:171 
  at Xamarin.Forms.Platform.iOS.ButtonElementManager.OnButtonTouchUpInside (Xamarin.Forms.IButtonController element) [0x00009] in D:\a\1\s\Xamarin.Forms.Platform.iOS\Renderers\ButtonElementManager.cs:86 
  at Xamarin.Forms.Platform.iOS.ButtonRenderer.OnButtonTouchUpInside (System.Object sender, System.EventArgs eventArgs) [0x00000] in D:\a\1\s\Xamarin.Forms.Platform.iOS\Renderers\ButtonRenderer.cs:147 
  at UIKit.UIControlEventProxy.Activated () [0x00004] in /Library/Frameworks/Xamarin.iOS.framework/Versions/13.16.0.13/src/Xamarin.iOS/UIKit/UIControl.cs:38 
--- End of stack trace from previous location where exception was thrown ---

  at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain(int,string[],intptr,intptr)
  at UIKit.UIApplication.Main (System.String[] args, System.IntPtr principal, System.IntPtr delegate) [0x00005] in /Library/Frameworks/Xamarin.iOS.framework/Versions/13.16.0.13/src/Xamarin.iOS/UIKit/UIApplication.cs:86 
  at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0000e] in /Library/Frameworks/Xamarin.iOS.framework/Versions/13.16.0.13/src/Xamarin.iOS/UIKit/UIApplication.cs:65 
  at ObservableCollectionTest.iOS.Application.Main (System.String[] args) [0x00001] in /Users/jsuarez/Downloads/ObservableCollectionTest/ObservableCollectionTest/ObservableCollectionTest.iOS/Main.cs:17 
 --- inner exception ---
Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index (System.ArgumentOutOfRangeException)
  at System.Collections.Generic.List`1[T].get_Item (System.Int32 index) [0x00009] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/Common/src/CoreLib/System/Collections/Generic/List.cs:161 
  at System.Collections.ObjectModel.Collection`1[T].System.Collections.IList.get_Item (System.Int32 index) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/Common/src/CoreLib/System/Collections/ObjectModel/Collection.cs:266 
  at Xamarin.Forms.Platform.iOS.ObservableItemsSource.ElementAt (System.Int32 index) [0x0000f] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ObservableItemsSource.cs:268 
  at Xamarin.Forms.Platform.iOS.ObservableItemsSource.get_Item (System.Int32 index) [0x00000] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ObservableItemsSource.cs:37 
  at Xamarin.Forms.Platform.iOS.ObservableItemsSource.GetIndexForItem (System.Object item) [0x00004] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ObservableItemsSource.cs:71 
  at Xamarin.Forms.Platform.iOS.CarouselViewController.CollectionItemsSourceChanged (System.Object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x0000c] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\CarouselViewController.cs:122 
  at Xamarin.Forms.Platform.iOS.ObservableItemsSource.CollectionChanged (System.Collections.Specialized.NotifyCollectionChangedEventArgs args) [0x00055] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ObservableItemsSource.cs:132 
  at Xamarin.Forms.Platform.iOS.ObservableItemsSource.CollectionChanged (System.Object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs args) [0x0002d] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ObservableItemsSource.cs:105 
  at System.Collections.ObjectModel.ObservableCollection`1[T].OnCollectionChanged (System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x00018] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/System.ObjectModel/src/System/Collections/ObjectModel/ObservableCollection.cs:263 
  at System.Collections.ObjectModel.ObservableCollection`1[T].OnCollectionChanged (System.Collections.Specialized.NotifyCollectionChangedAction action, System.Object item, System.Int32 index) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/System.ObjectModel/src/System/Collections/ObjectModel/ObservableCollection.cs:338 
  at System.Collections.ObjectModel.ObservableCollection`1[T].RemoveItem (System.Int32 index) [0x00021] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/System.ObjectModel/src/System/Collections/ObjectModel/ObservableCollection.cs:182 
  at System.Collections.ObjectModel.Collection`1[T].RemoveAt (System.Int32 index) [0x00027] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/Common/src/CoreLib/System/Collections/ObjectModel/Collection.cs:144 
  at ObservableCollectionTest.MainPage.Callback (Xamarin.Forms.Page page) [0x0001d] in /Users/jsuarez/Downloads/ObservableCollectionTest/ObservableCollectionTest/ObservableCollectionTest/MainPage.xaml.cs:40 
  at (wrapper managed-to-native) System.Reflection.RuntimeMethodInfo.InternalInvoke(System.Reflection.RuntimeMethodInfo,object,object[],System.Exception&)
  at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x0006a] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/mcs/class/corlib/System.Reflection/RuntimeMethodInfo.cs:395

Similar issues have been reported a few times now over the last 5 months without resolution. CollectionViews, and by the looks of this issue - CarouselViews, simply don't support offscreen ObservableCollection changes (add or delete). It was broken in December and I haven't seen any urgency in trying to fix it. I pity the poor developer potentially tasked with updating the VS template for a XF Shell based app to use the latest and greatest CollectionView instead of the old ListView.

Hi everyone can you try this package, I think it's fixed on next 4.6

Xamarin.Forms.4.6.0.691.nupkg.zip

I was looking at the sample, are you Subscribing twice to the Message, since when the Modal is disposed the appearing of the MainPage is called again*

Hi everyone can you try this package, I think it's fixed on next 4.6
Xamarin.Forms.4.6.0.691.nupkg.zip

Well done! It looks like you fixed the ObservableCollection issues. That package supports offscreen additions and deletions and doesn't appear to leave behind empty rows etc. Now if you could just fix the iOS grid layout and horizontal item spacing bugs I might finally be able to get a CollectionView into production. ;-)

I was looking at the sample, are you Subscribing twice to the Message, since when the Modal is disposed the appearing of the MainPage is called again*

Yes, in the sample it is, quick sample project 馃懠...
But in the real life case the message is only subscribed once.

Was this page helpful?
0 / 5 - 0 ratings