Skip to content

Conversation

@prakashKannanSf3972
Copy link
Contributor

@prakashKannanSf3972 prakashKannanSf3972 commented May 23, 2025

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Root Cause

  • SubscribeToItemsLayoutPropertyChanged subscribes to the PropertyChanged event to track changes in the layout.
  • However, when the ItemsLayout is updated, new PropertyChanged event handlers are added without removing the previously registered handlers.
  • This causes the number of event handlers to accumulate exponentially with each update.
  • As a result, each layout change triggers multiple redundant calls to UpdateLayout(), causing cascading layout recalculations and severe performance degradation.

Description of Change

  • Properly unsubscribed from ItemsLayout.PropertyChanged by invoking a dedicated cleanup method in DisconnectHandler() before the base disposal logic.
  • Ensured existing event handlers are unsubscribed before assigning new ones in SubscribeToItemsLayoutPropertyChanged().

Tested the behaviour in the following platforms

  • Android
  • Windows
  • iOS
  • Mac

Issues Fixed

Fixes #27666
Fixes #27667
Fixes #29619

Output

Before After
Before_Fix.mov
After_Fix.mov

@dotnet-policy-service dotnet-policy-service bot added the community ✨ Community Contribution label May 23, 2025
@dotnet-policy-service
Copy link
Contributor

Hey there @@prakashKannanSf3972! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@dotnet-policy-service dotnet-policy-service bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label May 23, 2025
@jsuarezruiz
Copy link
Contributor

/azp run MAUI-UITests-public

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@prakashKannanSf3972 prakashKannanSf3972 changed the title [iOS] - Fix Inconsistent Spacing Update Behavior in CollectionView for Vertical List and Grid Layouts [iOS] - Fixed the performance issue that occurred when updating the Spacing in CollectionView for both Vertical List and Grid layouts May 23, 2025
@prakashKannanSf3972 prakashKannanSf3972 marked this pull request as ready for review May 23, 2025 13:31
Copilot AI review requested due to automatic review settings May 23, 2025 13:31
@prakashKannanSf3972 prakashKannanSf3972 requested a review from a team as a code owner May 23, 2025 13:31
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes a severe performance degradation in CollectionView updates by preventing the exponential accumulation of PropertyChanged event registrations. The key changes include unsubscribing existing event handlers before adding new ones, overriding DisconnectHandler to remove event handlers on disconnect, and updating the public API files to reflect these changes.

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue27666.cs Added UI test verifying issue behavior
src/Controls/tests/TestCases.HostApp/Issues/Issue27666.cs Updated HostApp test for CollectionView spacing update
src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt Updated public API with DisconnectHandler override
src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt Updated public API with DisconnectHandler override
src/Controls/src/Core/Handlers/Items2/CollectionViewHandler2.iOS.cs Modified event handler subscription logic and added DisconnectHandler override
Comments suppressed due to low confidence (1)

src/Controls/tests/TestCases.HostApp/Issues/Issue27666.cs:91

  • [nitpick] The UI test only triggers the spacing update without validating that the spacing has actually changed. Consider adding assertions to verify that the layout property is updated as expected.
void OnItemSpacingButtonClicked(object sender, EventArgs e)

Comment on lines 91 to 53
void OnItemSpacingButtonClicked(object sender, EventArgs e)
{
if (collectionView.ItemsLayout is LinearItemsLayout layout)
{
layout.ItemSpacing = layout.ItemSpacing == 0 ? 50 : 20;
Copy link

Copilot AI May 23, 2025

Choose a reason for hiding this comment

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

[nitpick] Consider extracting the magic numbers (50 and 20) into named constants to improve code maintainability and clarity.

Suggested change
void OnItemSpacingButtonClicked(object sender, EventArgs e)
{
if (collectionView.ItemsLayout is LinearItemsLayout layout)
{
layout.ItemSpacing = layout.ItemSpacing == 0 ? 50 : 20;
const double DefaultItemSpacing = 50;
const double AlternateItemSpacing = 20;
void OnItemSpacingButtonClicked(object sender, EventArgs e)
{
if (collectionView.ItemsLayout is LinearItemsLayout layout)
{
layout.ItemSpacing = layout.ItemSpacing == 0 ? DefaultItemSpacing : AlternateItemSpacing;

Copilot uses AI. Check for mistakes.
*REMOVED*override Microsoft.Maui.Controls.Handlers.Compatibility.FrameRenderer.MovedToWindow() -> void
override Microsoft.Maui.Controls.Handlers.Compatibility.VisualElementRenderer<TElement>.MovedToWindow() -> void
override Microsoft.Maui.Controls.Handlers.Compatibility.VisualElementRenderer<TElement>.MovedToWindow() -> void
~override Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.DisconnectHandler(UIKit.UIView platformView) -> void
Copy link

Copilot AI May 23, 2025

Choose a reason for hiding this comment

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

The introduction of a new override for DisconnectHandler in the public API could constitute a breaking change. Please ensure that the public documentation is updated accordingly and that consumers are aware of this update.

Copilot uses AI. Check for mistakes.
*REMOVED*override Microsoft.Maui.Controls.Handlers.Compatibility.FrameRenderer.SetNeedsLayout() -> void
*REMOVED*override Microsoft.Maui.Controls.Handlers.Compatibility.FrameRenderer.MovedToWindow() -> void
override Microsoft.Maui.Controls.Handlers.Compatibility.VisualElementRenderer<TElement>.MovedToWindow() -> void
~override Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2.DisconnectHandler(UIKit.UIView platformView) -> void
Copy link

Copilot AI May 23, 2025

Choose a reason for hiding this comment

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

The introduction of a new override for DisconnectHandler in the public API could constitute a breaking change. Please ensure that the public documentation is updated accordingly and that consumers are aware of this update.

Copilot uses AI. Check for mistakes.
@jsuarezruiz jsuarezruiz added platform/ios area-controls-collectionview CollectionView, CarouselView, IndicatorView labels May 26, 2025
Copy link
Contributor

@jsuarezruiz jsuarezruiz left a comment

Choose a reason for hiding this comment

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

The test RefreshShouldNotChangeSize is failing on iOS.
Snapshot different than baseline: RefreshShouldNotChangeSize.png (10.83% difference)
image

Could you verify if is related with the changes?

@prakashKannanSf3972
Copy link
Contributor Author

The test RefreshShouldNotChangeSize is failing on iOS. Snapshot different than baseline: RefreshShouldNotChangeSize.png (10.83% difference) image

Could you verify if is related with the changes?

@jsuarezruiz , The test RefreshShouldNotChangeSize is currently failing in the CI on iOS, however, the same test passes locally with both CV1 and CV2 handlers. Could you please re-run the CI to verify if the issue persists.

jsuarezruiz
jsuarezruiz previously approved these changes Jun 2, 2025
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.

Let's review
#29638

@PureWeen PureWeen added this to the .NET 9 SR8 milestone Jun 2, 2025
@PureWeen PureWeen moved this to Ready To Review in MAUI SDK Ongoing Jun 2, 2025
@PureWeen PureWeen modified the milestones: .NET 9 SR8, .NET 9 SR9 Jun 2, 2025
@jsuarezruiz jsuarezruiz self-requested a review July 1, 2025 05:56
@jsuarezruiz
Copy link
Contributor

@prakashKannanSf3972 Could you rebase and fix the conflicts? Thanks in advance.

@prakashKannanSf3972
Copy link
Contributor Author

@prakashKannanSf3972 Could you rebase and fix the conflicts? Thanks in advance.

@jsuarezruiz, The conflicts have been resolved. Thanks.

@PureWeen PureWeen modified the milestones: .NET 9 SR9, .NET 9 SR10 Jul 3, 2025
@PureWeen PureWeen modified the milestones: .NET 9 SR10, .NET 9 SR11 Aug 4, 2025
@PureWeen PureWeen modified the milestones: .NET 9 SR11, .NET 9 SR12 Sep 10, 2025
@PureWeen PureWeen added the p/0 Current heighest priority issues that we are targeting for a release. label Sep 10, 2025
@PureWeen
Copy link
Member

#29683

@PureWeen PureWeen closed this Sep 11, 2025
@github-project-automation github-project-automation bot moved this from Ready To Review to Done in MAUI SDK Ongoing Sep 11, 2025
@github-actions github-actions bot locked and limited conversation to collaborators Oct 12, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-controls-collectionview CollectionView, CarouselView, IndicatorView community ✨ Community Contribution p/0 Current heighest priority issues that we are targeting for a release. partner/syncfusion Issues / PR's with Syncfusion collaboration platform/ios

Projects

Status: Done

3 participants