Notice (2018-05-24): bugzilla.xamarin.com is now in
Please join us on
Visual Studio Developer Community and in the
Mono organizations on
GitHub to continue tracking issues. Bugzilla will remain
available for reference in read-only mode. We will continue to work
on open Bugzilla bugs, copy them to the new locations
as needed for follow-up, and add the new items under Related
Our sincere thanks to everyone who has contributed on this bug
tracker over the years. Thanks also for your understanding as we
make these adjustments and improvements for the future.
Please create a new report for Bug 51754 on
Developer Community or GitHub if you have new
information to add and do not yet see a matching new report.
If the latest results still closely match this report, you can use the
In special cases on GitHub you might also want the comments:
GitHub Markdown with public comments
Created attachment 19472 [details]
Demo app with repro steps
Using Xamarin.Forms 184.108.40.206 Stable
We have been chasing a problem with the following situation with Xamarin.Forms ListView on iOS:
We have a ListView for which the ItemsSource is a ObservableRangeCollection (from James Montemagno's MvvmHelpers library). The ListView has a "Delete" ContextAction which does what you'd expect: delete the current row. We noticed (on iOS) that upon deleting the row, the row disappears from the ListView, however the Delete context action remains visible on the row that is now displayed in its place. CachingStrategy is set to RecycleElement. The problems do not occur when using RetainElement.
At first we thought there was a bug with the a cached ViewCell being reused and not properly reset, but we found out that the source of the problem was the way we were updating the underlying datasource.
Instead of just removing the item from the ObservableRangeCollection, we manipulated a List we kept in memory and then replaced the entire range with ObservableRangeCollection.ReplaceRange(). This triggers a CollectionChanged event with: NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset). The deleted row will be gone, but the state of the ViewCell remains and is now visible on the row what was directly below the row that was just deleted. When we changed this to do a Remove() of the item on the ObservableRangeCollection, a CollectionChanged event with NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove) is raised, and the ListView behaves as it should.
This happens only on iOS. On Android (using Long Press) the app crashes with a NullReferenceException when using DeleteWithReplaceRange (and CachingStrategy=RecycleElement):
at Xamarin.Forms.Platform.Android.CellAdapter.set_ContextView (Android.Views.View value) [0x00012] in C:\BuildAgent2\work\ca3766cfc22354a1\Xamarin.Forms.Platform.Android\CellAdapter.cs:67
at Xamarin.Forms.Platform.Android.ListViewAdapter.GetView (System.Int32 position, Android.Views.View convertView, Android.Views.ViewGroup parent) [0x000e8] in C:\BuildAgent2\work\ca3766cfc22354a1\Xamarin.Forms.Platform.Android\Renderers\ListViewAdapter.cs:218
at Android.Widget.BaseAdapter.n_GetView_ILandroid_view_View_Landroid_view_ViewGroup_ (System.IntPtr jnienv, System.IntPtr native__this, System.Int32 position, System.IntPtr native_convertView, System.IntPtr native_parent) [0x0001a] in /Users/builder/data/lanes/4009/0ab90794/source/monodroid/src/Mono.Android/platforms/android-23/src/generated/Android.Widget.BaseAdapter.cs:443
at (wrapper dynamic-method) System.Object:97245d05-9ae7-4983-ae1d-26731c05f853 (intptr,intptr,int,intptr,intptr)
I've attached a sample app (based on the Xamarin "Working With ListView" sample) that demonstrates the behaviour. In the solution, open ContextActionsXaml.xaml.cs and alternate between the different implementations of the OnDelete method. Calling DeleteWithReplaceRange will show the "wrong" behaviour, calling DeleteWithRemove will show the behaviour we expect.
Start the application on both iOS and Android and delete one of the rows (not the last one) by revealing the context menu and pressing the red Delete button. When using DeleteWithReplaceRange, on iOS the row will disappear but the context menu remains open on the next row. On Android, the app will crash. When using DeleteWithRemove, the behaviour is as expected on iOS, but the app still crashes on Android.
In the Xaml, change the CachingStrategy to RetainElement and observe that the app works on both platforms (although the row animations on iOS are different between the implementations).
I was able to reproduce this issue with the attached repro project and Forms 220.127.116.11 on both iOS and Android. As described, on iOS the context menu would remain open at the same row index as the just removed item, and on Android the app would crash.
However, I also tested with Forms 2.3.4-pre5 and the issue appears to be partially resolved. With the newer version the Android app would no longer crash and it worked as expected, but on iOS the same issue still occurs. Therefore I am confirming this report so the team can investigate further.
# Version Tests
- iOS: BAD, context menu remains open
- Android: GOOD
## Forms 18.104.22.168
- iOS: BAD, context menu remains open
- Android: BAD, crashes
We also encountered this issue with our ObservableCollection source when using the NotifyCollectionChangedAction.Reset action.
We found our ContextActions relating to the wrong elements (elements that were deleted before Reset was raised).
Setting the CachingStrategy to RetainElement resolves our issue too.
Reproduced on 22.214.171.124-pre6
- iOS: BAD
- Android: GOOD
This is still an issue in 2.3.5-pre3 and nightly. I'm reconfirming this issue and bumping up the priority.
I loaded up the iOS app, swipe to reveal the delete button, and deleted one of the middle rows. The row deleted and the table updated, but the context delete button remained. This does not happen when deleting the bottom row.
I know this one is quite old but it seems it is happening (again?) with latest XF 126.96.36.1994934, at least on iOS.
Is there a status other than CONFIRMED?