Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for CollectionView with RefreshView when ObservableCollection<T>.Clear() throws System.ArgumentOutOfRangeException #26573

Merged
merged 3 commits into from
Jan 6, 2025

Conversation

SuthiYuvaraj
Copy link
Contributor

@SuthiYuvaraj SuthiYuvaraj commented Dec 12, 2024

Root Cause:

The issue arises because the UICollectionView's internal _itemSource becomes empty during pull-to-refresh, even though the ItemsSource in the controller still holds a valid count. This discrepancy causes an invalid state, where the GetSizeForItem method tries to access an index that no longer exists, resulting in a System.ArgumentOutOfRangeException. The issue was further compounded by the fact that GetSizeForItem was being called before the CollectionChanged event was triggered. This occurs because the ContentOffset is set during the pull-to-refresh operation, which prematurely triggers layout recalculations, leading to an invalid state.

Description of Change:

The change ensures the ElementAt method safely accesses elements by validating the index with (index >= 0 && index < list.Count). Using a ternary operator, it immediately returns the item or -1 for invalid indices, preventing System.ArgumentOutOfRangeException and simplifying the logic for better reliability.

Issues Fixed

Fixes #23868

Tested the behaviour in the following platforms

  • Android
  • Windows
  • iOS
  • Mac

###Output Video

Before Issue Fix After Issue Fix
withoutfix.mov
withfix.mov

@dotnet-policy-service dotnet-policy-service bot added the community ✨ Community Contribution label Dec 12, 2024
@jfversluis jfversluis added the area-controls-collectionview CollectionView, CarouselView, IndicatorView label Dec 12, 2024
@sheiksyedm sheiksyedm added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Dec 12, 2024
@SuthiYuvaraj SuthiYuvaraj marked this pull request as ready for review December 12, 2024 13:31
Copy link
Member

@PureWeen PureWeen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add the following test to this PR?

public class Issue7678Ios : TestContentPage

When you copy the test over can you make sure to put it inside the XFIssue folder?

image

It looks like the ObservableItemSource changes were made in the following PR xamarin/Xamarin.Forms#7711 and I worry that the fixes here are reverting those fixes a bit.

@PureWeen PureWeen added this to the .NET 9 SR3 milestone Dec 12, 2024
@praveenkumarkarunanithi
Copy link
Contributor

praveenkumarkarunanithi commented Dec 13, 2024

Can you add the following test to this PR?

public class Issue7678Ios : TestContentPage

When you copy the test over can you make sure to put it inside the XFIssue folder?

image

It looks like the ObservableItemSource changes were made in the following PR xamarin/Xamarin.Forms#7711 and I worry that the fixes here are reverting those fixes a bit.

@PureWeen Regarding the changes to ObservableItemSource, we’d like to clarify that our fix now ensures functionality without modifying the Count property directly. Instead, we’ve implemented proper index validation to prevent exceptions when the list is empty or the index is out of range. This approach preserves the integrity of the existing logic and aligns with the previous changes introduced in PR xamarin/Xamarin.Forms#7711.
Additionally, we ensured the Issue7678 test case works as expected with the fix.

@jfversluis jfversluis requested a review from PureWeen December 16, 2024 10:24
@jfversluis
Copy link
Member

/azp run

Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@rmarinho rmarinho self-assigned this Dec 16, 2024
@rmarinho rmarinho self-requested a review December 16, 2024 14:52
@@ -279,7 +279,7 @@ internal int ItemsCount()
internal object ElementAt(int index)
{
if (_itemsSource is IList list)
return list[index];
return (index >= 0 && index < list.Count) ? list[index] : -1;
Copy link
Member

@mattleibow mattleibow Dec 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the ElementAt call, so should return the object or null, not -1 (index). I also see further down it is also returning -1, which is also quite wrong. If we now start returning null, what else will break?

I think this code was copied from the IndexOf method below.

But also, if we are getting here, there is something else wrong - the collection view is rendering a non-existent item? How did it get to this point?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mattleibow You are correct. Previously, we returned -1 based on the existing else part value. Now, we have changed the return value from -1 to null. Returning null is a more appropriate approach when a requested item does not exist in the ElementAt method. Please let us know if you have any concerns or additional feedback regarding this change.

@PureWeen
Copy link
Member

/azp run

Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@mattleibow
Copy link
Member

@PureWeen Should something still be done with your comment about putting things in the XFIssue folder?

@PureWeen PureWeen merged commit 0513686 into dotnet:main Jan 6, 2025
105 checks passed
@PureWeen
Copy link
Member

PureWeen commented Jan 9, 2025

@mattleibow we're good

Another issue/pr was created to cover that case

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-controls-collectionview CollectionView, CarouselView, IndicatorView community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

ObservableCollection<T>.Clear() throws System.ArgumentOutOfRangeException
7 participants