Skip to content

[Windows] Fix for Grouping collection view without data template results in displaying the default string representation of the object#28617

Open
SyedAbdulAzeemSF4852 wants to merge 13 commits intodotnet:mainfrom
SyedAbdulAzeemSF4852:fix-23293
Open

Conversation

@SyedAbdulAzeemSF4852
Copy link
Copy Markdown
Contributor

Issue Details

  • Grouping collection view without data template results in displaying the default string representation of the object.

Root Cause

  • When an itemTemplate is not specified, a default template is being applied. This leads to binding issues where the expected data cannot be properly bound to the UI elements, causing the ToString() method of the bound object to be invoked as a fallback. This results in the display of the default string representation of the object.

Description of Change

  • If both itemTemplate and itemsSource are not null, created the grouped collection by using the provided item template and the source data. If either itemTemplate or itemsSource is null, then created the grouped collection view directly from the itemsSource without any templates.

Validated the behaviour in the following platforms

  • Windows
  • Android
  • iOS
  • Mac

Issues Fixed

Fixes #23293

Output

Before Fix After Fix
Before.mp4
After.mp4

@dotnet-policy-service dotnet-policy-service bot added the community ✨ Community Contribution label Mar 26, 2025
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Hey there @SyedAbdulAzeemSF4852! 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 Mar 26, 2025
@jsuarezruiz
Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

IsSourceGrouped = true,
ItemsPath = new Microsoft.UI.Xaml.PropertyPath(nameof(GroupTemplateContext.Items))
};
return new CollectionViewSource
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can encapsulate the logic within separate methods for better readability:

private CollectionViewSource CreateGroupedCollectionViewSource(object itemsSource, object itemTemplate)
{
    return new CollectionViewSource
    {
        Source = TemplatedItemSourceFactory.CreateGrouped(itemsSource, itemTemplate,
        ItemsView.GroupHeaderTemplate, ItemsView.GroupFooterTemplate, Element, mauiContext: MauiContext),
        IsSourceGrouped = true,
        ItemsPath = new Microsoft.UI.Xaml.PropertyPath(nameof(GroupTemplateContext.Items))
    };
}

// Creates and returns a grouped CollectionViewSource using itemsSource as the data source when an itemTemplate is not defined.
private CollectionViewSource CreateDefaultGroupedCollectionViewSource(object itemsSource)
{
    return new CollectionViewSource
    {
        Source = itemsSource,
        IsSourceGrouped = true,
    };
}
return (itemTemplate is not null && itemsSource is not null)
    ? CreateGroupedCollectionViewSource(itemsSource, itemTemplate)
    : CreateDefaultGroupedCollectionViewSource(itemsSource);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@jsuarezruiz , As suggested have encapsulated the logic within separate methods for better readability.

@jfversluis jfversluis added the area-controls-collectionview CollectionView, CarouselView, IndicatorView label Mar 26, 2025
public void GroupedCollectionViewWithoutDataTemplate()
{
App.WaitForElement("CollectionViewWithoutDataTemplate");
VerifyScreenshot();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pending snapshots already available in the latest build.

Example, iOS:
image

Could you commit the images?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@jsuarezruiz , I have committed the snapshots.

@rmarinho
Copy link
Copy Markdown
Member

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@SyedAbdulAzeemSF4852 SyedAbdulAzeemSF4852 marked this pull request as ready for review April 2, 2025 16:53
@SyedAbdulAzeemSF4852 SyedAbdulAzeemSF4852 requested a review from a team as a code owner April 2, 2025 16:53
@jsuarezruiz
Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@jsuarezruiz
Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

}
}

private CollectionViewSource CreateGroupedCollectionViewSource(IEnumerable itemsSource, DataTemplate itemTemplate)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we drop private we don t use it in our code base

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@rmarinho , As suggested, I've removed the private modifier.

}

// Creates and returns a grouped CollectionViewSource using itemsSource as the data source when an itemTemplate is not defined.
private CollectionViewSource CreateDefaultGroupedCollectionViewSource(IEnumerable itemsSource)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
private CollectionViewSource CreateDefaultGroupedCollectionViewSource(IEnumerable itemsSource)
CollectionViewSource CreateDefaultGroupedCollectionViewSource(IEnumerable itemsSource)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@rmarinho , I've made the changes as mentioned.

}

// Creates and returns a grouped CollectionViewSource using itemsSource as the data source when an itemTemplate is not defined.
private CollectionViewSource CreateDefaultGroupedCollectionViewSource(IEnumerable itemsSource)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What happens if itemsSource is null?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@rmarinho, If itemsSource is null, the creation of the CollectionViewSource object will be skipped. However, in this PR, the null check for itemsSource in the UpdateItemsSource method has been removed, which means that if the PR is merged, a CollectionViewSource will be created with a null source.

@jsuarezruiz
Copy link
Copy Markdown
Contributor

/azp run MAUI-UITests-public

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

…te results in displaying the default string representation of the object)
…te results in displaying the default string representation of the object)
…te results in displaying the default string representation of the object)
…te results in displaying the default string representation of the object)
…te results in displaying the default string representation of the object)
…te results in displaying the default string representation of the object)
Copy link
Copy Markdown
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 Windows-specific issue where CollectionView with grouping displays the default string representation (ToString()) of objects when no ItemTemplate is provided. The fix ensures that when an ItemTemplate is not specified, the data is bound directly without applying a default template that causes binding issues.

Key Changes:

  • Modified the CollectionViewSource creation logic to handle grouped collections differently based on whether an ItemTemplate is provided
  • Added two helper methods to distinguish between templated and non-templated grouped collection view scenarios

Reviewed changes

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

File Description
src/Controls/src/Core/Handlers/Items/GroupableItemsViewHandler.Windows.cs Refactored CollectionViewSource creation to conditionally apply templates, extracting logic into separate methods for templated vs. non-templated grouped collections
src/Controls/tests/TestCases.HostApp/Issues/Issue23293.cs Added test case demonstrating grouped CollectionView without ItemTemplate using animal groups
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue23293.cs Added UI test to verify the fix via screenshot validation

@kubaflo
Copy link
Copy Markdown
Contributor

kubaflo commented Mar 18, 2026

🤖 AI Summary

📊 Expand Full Review2b56ab2 · Have updated the test case and have added the iOS snapshot
🔍 Pre-Flight — Context & Validation

Issue: #23293 - [MAUI] I6 Grouping - 'Grouping for Vertical list without DataTemplates' page loading exception
PR: #28617 - [Windows] Fix for Grouping collection view without data template results in displaying the default string representation of the object
Platforms Affected: Windows (issue repro); PR author also validated Android, iOS, and Mac snapshots for regression coverage
Files Changed: 1 implementation, 2 test code, 4 snapshot

Key Findings

  • The linked issue is Windows-only and reproduces when CollectionView uses grouped data without an ItemTemplate; expected grouped animal names do not render.
  • The PR changes only GroupableItemsViewHandler.Windows.cs, adds a HostApp issue page plus a screenshot-based UI test, and commits platform snapshots for Android, iOS, Mac, and Windows.
  • Existing review discussion focused on readability refactoring, removing explicit private, narrowing helper parameter types to IEnumerable, and a remaining edge-case question about itemsSource == null.
  • No prior PRAgent phase output was found in PR comments; the only bot review present is a generic Copilot PR reviewer summary.

Edge Cases From Discussion

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #28617 When grouping on Windows, use templated grouped source only when both itemTemplate and itemsSource are non-null; otherwise create a grouped CollectionViewSource directly from itemsSource without templates. PENDING (Gate) src/Controls/src/Core/Handlers/Items/GroupableItemsViewHandler.Windows.cs, src/Controls/tests/TestCases.HostApp/Issues/Issue23293.cs, src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue23293.cs, snapshot files Original PR

🚦 Gate — Test Verification

Result: FAILED

Gate Result: FAILED

Platform: windows
Mode: Full Verification

  • Tests FAIL without fix:
  • Tests PASS with fix:

Notes

  • Without the PR fix, Issue23293.GroupedCollectionViewWithoutDataTemplate failed as expected with a visual regression against the stored snapshot.
  • With the PR fix applied, the same verification failed on Windows with a timeout waiting for the target UI element.
  • Gate conclusion: the test catches the bug, but the PR's current fix does not make the verification pass on the selected platform.

🔧 Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix Move the no-template decision into TemplatedItemSourceFactory.CreateGrouped, returning raw grouped data when no item template exists, and let the Windows handler set ItemsPath only for GroupedItemTemplateCollection. PASS 3 files Passing alternative, but broader than candidate 2 because it changes both the factory and handler.
2 try-fix Keep grouped wrapper behavior intact, but in GroupedItemTemplateCollection.CreateGroupTemplateContext expose raw group items when _itemTemplate is null instead of wrapping them in ItemTemplateContext. PASS 1 code file + Windows snapshot Strongest passing candidate: smallest production change and preserves the grouped wrapper pipeline.
3 try-fix Change the default projection in TemplatedItemSourceFactory.Create for null templates and suppress wrapper text by overriding GroupTemplateContext.ToString(). FAIL 2 files Still produced a Windows screenshot mismatch (~4.09% difference).
4 try-fix Introduce an interface so GroupTemplateContext can unwrap item-wrapper collections back to their original data source when ItemTemplate is null. FAIL 4 files Functionally close, but still failed visual verification (~4.09% difference).
5 try-fix Inject an internal grouped fallback DataTemplate on Windows when ItemTemplate is null, while keeping grouped wrappers and ItemsPath intact. FAIL 1 file Avoided null-template data branching, but still produced the same ~4.09% screenshot mismatch.
6 try-fix Use native DisplayMemberPath = nameof(ItemTemplateContext.Item) for grouped Windows items without an item template. PASS (weakened test) 1 code file + 1 test file Functional text-based check passed only after weakening the verification away from screenshot validation.
7 try-fix Leave the data pipeline intact and instead route grouped null-template items through ItemContentControl, which renders a native fallback TextBlock when FormsDataTemplate is null. PASS 2 production files + HostApp test data Passed screenshot verification, but is broader than candidate 2 and reaches deeper into the rendering path.
PR PR #28617 Special-case grouped Windows CollectionViewSource creation in GroupableItemsViewHandler.Windows so templated grouping is used only when both itemTemplate and itemsSource are non-null, otherwise bind the raw grouped source directly. FAIL (Gate) 3 code/test files + snapshots Original PR times out on Windows during verification.

Cross-Pollination

Model Round New Ideas? Details
claude-opus-4.6 1 Yes Factory-level grouped-source fallback plus adaptive handler ItemsPath passed.
claude-sonnet-4.6 1 Yes Grouped item materialization fallback inside GroupedItemTemplateCollection passed.
gpt-5.3-codex 1 Yes Projection-layer passthrough plus GroupTemplateContext.ToString() failed.
gemini-3-pro-preview 1 Yes Wrapper-unwrapping in GroupTemplateContext failed.
gpt-5.3-codex 2 Yes Injecting a fallback grouped item template failed.
gemini-3-pro-preview 2 Yes Native DisplayMemberPath passed only with weakened verification.
claude-sonnet-4.6 2 Yes Suggested rendering-layer fallback rather than another data-pipeline change.
claude-opus-4.6 2 Yes Suggested routing grouped null-template items through ItemContentControl; that approach passed as candidate 7.
gpt-5.3-codex 3 Yes Proposed source-shaping to lightweight bindable objects; not run because stronger passing alternatives already existed.
gemini-3-pro-preview 3 Yes Proposed ContainerContentChanging manual unwrapping; not run because stronger passing alternatives already existed.
claude-opus-4.6 3 No No new materially different ideas after comparing all seven attempts; passing strategies already cover the viable layers.
claude-sonnet-4.6 3 Blocked Timed out during final exhaustion query.

Exhausted: No
Selected Fix: Candidate #2 Best balance of correctness, simplicity, and consistency. It fixes the grouped no-template case at the point where bad wrappers are created, without broad rendering-path changes or weakened verification.


📋 Report — Final Recommendation

Final Recommendation: REQUEST CHANGES

Phase Status

Phase Status Notes
Pre-Flight COMPLETE Linked issue #23293 is Windows-only; PR changes one Windows handler plus UI test assets.
Gate FAILED Windows verification reproduced the bug without the fix, but the PR fix still failed with a timeout waiting for the target element.
Try-Fix COMPLETE 7 attempts: 3 strong passes, 1 weakened pass, 3 failures. Best alternative was candidate 2.
Report COMPLETE

Summary

The PR should not be merged in its current form. The gate showed that the new test catches the bug, but the PR's handler-level fix still fails on Windows. Independent exploration found multiple alternatives that do pass, which means the problem is fixable but the current implementation is not the best path.

Root Cause

The failure is tied to how Windows grouped CollectionView materializes or renders leaf items when ItemTemplate is null. The PR tries to bypass that by branching in GroupableItemsViewHandler.Windows, but verified Windows execution still times out. The strongest alternative fix instead addresses the grouped item materialization point directly by exposing raw group items when no template exists.

Fix Quality

The PR fix is not shippable as written because it fails the Windows gate. Candidate 2 is a better direction: it is smaller, stays within the existing grouped wrapper model, and passed validation without weakening the test. Candidate 7 also passed, but it is broader because it changes the rendering path and required more supporting adjustments.


📋 Expand PR Finalization Review

PR #28617 Finalization Review

Title Review

Current: [Windows] Fix for Grouping collection view without data template results in displaying the default string representation of the object

Assessment: Needs a tighter, more searchable title.

Recommended: [Windows] CollectionView: Fix grouped rendering without ItemTemplate

Why: the current title repeats the issue text verbatim and is harder to scan in git history. The recommended title keeps the platform + component prefix and describes the actual behavioral change.

Description Review

Assessment: Decent foundation, but not merge-ready as written.

What is good:

  • Includes a real root-cause section.
  • Includes a behavior description and issue link.
  • Accurately frames the change as Windows-specific.

What should be updated:

  • Add the required NOTE block at the very top from .github/PULL_REQUEST_TEMPLATE.md.
  • Prefer the standard ### Description of Change / ### Issues Fixed structure instead of leading with ### Issue Details.
  • Explicitly mention that the PR also adds UI coverage/snapshots for the reproduced scenario.
  • If the implementation changes, update the description accordingly: the current text says the grouped source is created directly from itemsSource when itemTemplate is null, but that fallback currently appears to introduce a grouped header/footer regression risk.

Action: Keep the existing root-cause narrative, prepend the NOTE block, and revise the implementation details before merge.

Code Review Findings

Critical Issues

Grouped header/footer templates are likely regressed in the new Windows fallback path

  • File: src/Controls/src/Core/Handlers/Items/GroupableItemsViewHandler.Windows.cs
  • Problem: The new CreateDefaultGroupedCollectionViewSource(IEnumerable itemsSource) path bypasses TemplatedItemSourceFactory.CreateGrouped(...) and returns the raw grouped source directly when ItemTemplate is null.
  • Why this matters: On Windows, grouped rendering relies on GroupTemplateContext for group metadata. GroupedItemTemplateCollection creates that wrapper and populates HeaderItemTemplateContext / FooterItemTemplateContext (src/Controls/src/Core/Platform/Windows/CollectionView/GroupedItemTemplateCollection.cs, GroupTemplateContext.cs). The Windows group header template then binds its DataContext to HeaderItemTemplateContext (src/Controls/src/Core/Platform/Windows/CollectionView/ItemsViewStyles.xaml). If the source is raw groups instead of GroupTemplateContext, GroupHeaderTemplate / GroupFooterTemplate cannot work correctly.
  • Evidence: Existing UI coverage already validates grouped header/footer behavior (src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/CollectionView_GroupingFeatureTests.cs:250-308). Those scenarios depend on the same Windows group-template plumbing this fallback now skips.
  • Recommendation: Do not bypass the grouped wrapper. Preserve TemplatedItemSourceFactory.CreateGrouped(...) / GroupTemplateContext for grouped sources, and instead fix the no-ItemTemplate case lower in the pipeline so group headers/footers continue to function.

Suggestions

  • Add a targeted Windows test for the combination: IsGrouped = true, ItemTemplate = null, and GroupHeaderTemplate and/or GroupFooterTemplate set. The new test page only covers the no-template grouped-items scenario, so it would not catch the regression above.
  • When the description is updated, mention that the fix is Windows handler code plus cross-platform UI snapshots, so reviewers do not misread the added screenshots as cross-platform behavior changes.

Looks Good

  • The PR includes a focused reproduction page and a UI test for the reported issue (Issue23293), which is the right level of coverage for the original bug.
  • The handler change is narrowly scoped to the Windows grouped CollectionView path.

Overall Assessment

The metadata needs a small cleanup, but the larger concern is the Windows grouped-template regression risk. I would not consider this PR ready to merge until the grouped no-ItemTemplate fix preserves GroupTemplateContext behavior for GroupHeaderTemplate / GroupFooterTemplate.

@kubaflo kubaflo added s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-gate-failed AI could not verify tests catch the bug s/agent-fix-win AI found a better alternative fix than the PR s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Mar 18, 2026
Copy link
Copy Markdown
Contributor

@kubaflo kubaflo left a comment

Choose a reason for hiding this comment

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

Could you please apply the AI's suggestions?

@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Mar 20, 2026

🤖 AI Summary

📊 Expand Full Review2b56ab2 · Have updated the test case and have added the iOS snapshot
🔍 Pre-Flight — Context & Validation

Issue: #23293 - [MAUI] I6 Grouping - 'Grouping for Vertical list without DataTemplates' page loading exception
PR: #28617 - [Windows] Fix for Grouping collection view without data template results in displaying the default string representation of the object
Platforms Affected: Windows (issue repro); PR author also validated Android, iOS, and Mac snapshots for regression coverage
Files Changed: 1 implementation, 2 test code, 4 snapshot

Key Findings

  • The linked issue is Windows-only and reproduces when CollectionView uses grouped data without an ItemTemplate; expected grouped animal names do not render.
  • The PR changes only GroupableItemsViewHandler.Windows.cs, adds a HostApp issue page plus a screenshot-based UI test, and commits platform snapshots for Android, iOS, Mac, and Windows.
  • Existing review discussion focused on readability refactoring, removing explicit private, narrowing helper parameter types to IEnumerable, and a remaining edge-case question about itemsSource == null.
  • No prior PRAgent phase output was found in PR comments; the only bot review present is a generic Copilot PR reviewer summary.

Edge Cases From Discussion

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #28617 When grouping on Windows, use templated grouped source only when both itemTemplate and itemsSource are non-null; otherwise create a grouped CollectionViewSource directly from itemsSource without templates. PENDING (Gate) src/Controls/src/Core/Handlers/Items/GroupableItemsViewHandler.Windows.cs, src/Controls/tests/TestCases.HostApp/Issues/Issue23293.cs, src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue23293.cs, snapshot files Original PR

Issue: #23293 - [MAUI] I6 Grouping - 'Grouping for Vertical list without DataTemplates' page loading exception
PR: #28617 - [Windows] Fix for Grouping collection view without data template results in displaying the default string representation of the object
Platforms Affected: Windows (issue), PR claims validation on Windows/Android/iOS/Mac
Files Changed: 1 implementation, 2 test source files, 4 snapshot assets

Key Findings

  • The linked issue is a Windows-only CollectionView grouping bug: grouped items without an ItemTemplate show the default string representation instead of the animal names.
  • The implementation change is isolated to src/Controls/src/Core/Handlers/Items/GroupableItemsViewHandler.Windows.cs; added tests are a HostApp issue page plus a shared UI screenshot test (Issue23293).
  • Review discussion requested readability refactoring and snapshot commits; both were addressed in follow-up commits.
  • A reviewer explicitly asked what happens when itemsSource is null, and the author answered that the new fallback path can create a grouped CollectionViewSource with a null Source if upstream null checks are removed.
  • A prior agent review exists on the PR and the current labels already indicate a previous s/agent-reviewed, s/agent-changes-requested, s/agent-gate-failed, and s/agent-fix-win outcome.

Edge Cases Mentioned

  • itemsSource == null on the grouped fallback path remains a discussed edge case in review comments.
  • The added UI test is screenshot-based and verifies rendered output, not the null-itemsSource behavior.

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #28617 On Windows grouped CollectionView, use the templated grouped source only when both ItemTemplate and ItemsSource are non-null; otherwise create a grouped CollectionViewSource directly from ItemsSource. FAILED (Gate) src/Controls/src/Core/Handlers/Items/GroupableItemsViewHandler.Windows.cs, src/Controls/tests/TestCases.HostApp/Issues/Issue23293.cs, src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue23293.cs, snapshots Imported from prior PR agent review summary already posted on the PR.

🚦 Gate — Test Verification

Result: FAILED

Gate Result: FAILED

Platform: windows
Mode: Full Verification

  • Tests FAIL without fix:
  • Tests PASS with fix:

Notes

  • Without the PR fix, Issue23293.GroupedCollectionViewWithoutDataTemplate failed as expected with a visual regression against the stored snapshot.
  • With the PR fix applied, the same verification failed on Windows with a timeout waiting for the target UI element.
  • Gate conclusion: the test catches the bug, but the PR's current fix does not make the verification pass on the selected platform.

Result: FAILED

Gate Result: FAILED

Platform: windows
Mode: Full Verification

  • Tests FAIL without fix: Yes
  • Tests PASS with fix: No

Notes


🔧 Fix — Analysis & Comparison

Result: FAILED

Gate Result: FAILED

Platform: windows
Mode: Full Verification

  • Tests FAIL without fix:
  • Tests PASS with fix:

Notes

  • Without the PR fix, Issue23293.GroupedCollectionViewWithoutDataTemplate failed as expected with a visual regression against the stored snapshot.
  • With the PR fix applied, the same verification failed on Windows with a timeout waiting for the target UI element.
  • Gate conclusion: the test catches the bug, but the PR's current fix does not make the verification pass on the selected platform.

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix Move the no-template decision into TemplatedItemSourceFactory.CreateGrouped, returning raw grouped data when no item template exists, and let the Windows handler set ItemsPath only for GroupedItemTemplateCollection. PASS 3 files Passing alternative, but broader than candidate 2 because it changes both the factory and handler.
2 try-fix Keep grouped wrapper behavior intact, but in GroupedItemTemplateCollection.CreateGroupTemplateContext expose raw group items when _itemTemplate is null instead of wrapping them in ItemTemplateContext. PASS 1 code file + Windows snapshot Strongest passing candidate: smallest production change and preserves the grouped wrapper pipeline.
3 try-fix Change the default projection in TemplatedItemSourceFactory.Create for null templates and suppress wrapper text by overriding GroupTemplateContext.ToString(). FAIL 2 files Still produced a Windows screenshot mismatch (~4.09% difference).
4 try-fix Introduce an interface so GroupTemplateContext can unwrap item-wrapper collections back to their original data source when ItemTemplate is null. FAIL 4 files Functionally close, but still failed visual verification (~4.09% difference).
5 try-fix Inject an internal grouped fallback DataTemplate on Windows when ItemTemplate is null, while keeping grouped wrappers and ItemsPath intact. FAIL 1 file Avoided null-template data branching, but still produced the same ~4.09% screenshot mismatch.
6 try-fix Use native DisplayMemberPath = nameof(ItemTemplateContext.Item) for grouped Windows items without an item template. PASS (weakened test) 1 code file + 1 test file Functional text-based check passed only after weakening the verification away from screenshot validation.
7 try-fix Leave the data pipeline intact and instead route grouped null-template items through ItemContentControl, which renders a native fallback TextBlock when FormsDataTemplate is null. PASS 2 production files + HostApp test data Passed screenshot verification, but is broader than candidate 2 and reaches deeper into the rendering path.
PR PR #28617 Special-case grouped Windows CollectionViewSource creation in GroupableItemsViewHandler.Windows so templated grouping is used only when both itemTemplate and itemsSource are non-null, otherwise bind the raw grouped source directly. FAIL (Gate) 3 code/test files + snapshots Original PR times out on Windows during verification.

Cross-Pollination

Model Round New Ideas? Details
claude-opus-4.6 1 Yes Factory-level grouped-source fallback plus adaptive handler ItemsPath passed.
claude-sonnet-4.6 1 Yes Grouped item materialization fallback inside GroupedItemTemplateCollection passed.
gpt-5.3-codex 1 Yes Projection-layer passthrough plus GroupTemplateContext.ToString() failed.
gemini-3-pro-preview 1 Yes Wrapper-unwrapping in GroupTemplateContext failed.
gpt-5.3-codex 2 Yes Injecting a fallback grouped item template failed.
gemini-3-pro-preview 2 Yes Native DisplayMemberPath passed only with weakened verification.
claude-sonnet-4.6 2 Yes Suggested rendering-layer fallback rather than another data-pipeline change.
claude-opus-4.6 2 Yes Suggested routing grouped null-template items through ItemContentControl; that approach passed as candidate 7.
gpt-5.3-codex 3 Yes Proposed source-shaping to lightweight bindable objects; not run because stronger passing alternatives already existed.
gemini-3-pro-preview 3 Yes Proposed ContainerContentChanging manual unwrapping; not run because stronger passing alternatives already existed.
claude-opus-4.6 3 No No new materially different ideas after comparing all seven attempts; passing strategies already cover the viable layers.
claude-sonnet-4.6 3 Blocked Timed out during final exhaustion query.

Exhausted: No
Selected Fix: Candidate #2 Best balance of correctness, simplicity, and consistency. It fixes the grouped no-template case at the point where bad wrappers are created, without broad rendering-path changes or weakened verification.

Provenance


📋 Report — Final Recommendation

Final Recommendation: REQUEST CHANGES

Phase Status

Phase Status Notes
Pre-Flight COMPLETE Linked issue #23293 is Windows-only; PR changes one Windows handler plus UI test assets.
Gate FAILED Windows verification reproduced the bug without the fix, but the PR fix still failed with a timeout waiting for the target element.
Try-Fix COMPLETE 7 attempts: 3 strong passes, 1 weakened pass, 3 failures. Best alternative was candidate 2.
Report COMPLETE

Summary

The PR should not be merged in its current form. The gate showed that the new test catches the bug, but the PR's handler-level fix still fails on Windows. Independent exploration found multiple alternatives that do pass, which means the problem is fixable but the current implementation is not the best path.

Root Cause

The failure is tied to how Windows grouped CollectionView materializes or renders leaf items when ItemTemplate is null. The PR tries to bypass that by branching in GroupableItemsViewHandler.Windows, but verified Windows execution still times out. The strongest alternative fix instead addresses the grouped item materialization point directly by exposing raw group items when no template exists.

Fix Quality

The PR fix is not shippable as written because it fails the Windows gate. Candidate 2 is a better direction: it is smaller, stays within the existing grouped wrapper model, and passed validation without weakening the test. Candidate 7 also passed, but it is broader because it changes the rendering path and required more supporting adjustments.


Final Recommendation: REQUEST CHANGES

Phase Status

Phase Status Notes
Pre-Flight COMPLETE Linked issue #23293 is Windows-only; PR changes one Windows handler plus UI test assets.
Gate FAILED Windows verification reproduced the bug without the fix, but the PR fix still failed with a timeout waiting for the target element.
Try-Fix COMPLETE Imported prior results: 7 attempts, 4 passes including 1 weakened pass; best alternative was candidate 2.
Report COMPLETE Reconstructed from prior PR agent review summary.

Summary

The PR should not be merged in its current form. The gate showed that the new test catches the bug, but the PR's handler-level fix still fails on Windows. Independent exploration previously found multiple alternatives that do pass, which means the problem is fixable but the current implementation is not the best path.

Root Cause

The failure is tied to how Windows grouped CollectionView materializes or renders leaf items when ItemTemplate is null. The PR tries to bypass that by branching in GroupableItemsViewHandler.Windows, but verified Windows execution still timed out. The strongest alternative fix instead addresses the grouped item materialization point directly by exposing raw group items when no template exists.

Fix Quality

The PR fix is not shippable as written because it fails the Windows gate. Candidate 2 is a better direction: it is smaller, stays within the existing grouped wrapper model, and passed validation without weakening the test. Candidate 7 also passed, but it is broader because it changes the rendering path and required more supporting adjustments.


📋 Expand PR Finalization Review

PR #28617 Finalization Review

Title Review

Current: [Windows] Fix for Grouping collection view without data template results in displaying the default string representation of the object

Assessment: Needs a tighter, more searchable title.

Recommended: [Windows] CollectionView: Fix grouped rendering without ItemTemplate

Why: the current title repeats the issue text verbatim and is harder to scan in git history. The recommended title keeps the platform + component prefix and describes the actual behavioral change.

Description Review

Assessment: Decent foundation, but not merge-ready as written.

What is good:

  • Includes a real root-cause section.
  • Includes a behavior description and issue link.
  • Accurately frames the change as Windows-specific.

What should be updated:

  • Add the required NOTE block at the very top from .github/PULL_REQUEST_TEMPLATE.md.
  • Prefer the standard ### Description of Change / ### Issues Fixed structure instead of leading with ### Issue Details.
  • Explicitly mention that the PR also adds UI coverage/snapshots for the reproduced scenario.
  • If the implementation changes, update the description accordingly: the current text says the grouped source is created directly from itemsSource when itemTemplate is null, but that fallback currently appears to introduce a grouped header/footer regression risk.

Action: Keep the existing root-cause narrative, prepend the NOTE block, and revise the implementation details before merge.

Code Review Findings

Critical Issues

Grouped header/footer templates are likely regressed in the new Windows fallback path

  • File: src/Controls/src/Core/Handlers/Items/GroupableItemsViewHandler.Windows.cs
  • Problem: The new CreateDefaultGroupedCollectionViewSource(IEnumerable itemsSource) path bypasses TemplatedItemSourceFactory.CreateGrouped(...) and returns the raw grouped source directly when ItemTemplate is null.
  • Why this matters: On Windows, grouped rendering relies on GroupTemplateContext for group metadata. GroupedItemTemplateCollection creates that wrapper and populates HeaderItemTemplateContext / FooterItemTemplateContext (src/Controls/src/Core/Platform/Windows/CollectionView/GroupedItemTemplateCollection.cs, GroupTemplateContext.cs). The Windows group header template then binds its DataContext to HeaderItemTemplateContext (src/Controls/src/Core/Platform/Windows/CollectionView/ItemsViewStyles.xaml). If the source is raw groups instead of GroupTemplateContext, GroupHeaderTemplate / GroupFooterTemplate cannot work correctly.
  • Evidence: Existing UI coverage already validates grouped header/footer behavior (src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/CollectionView_GroupingFeatureTests.cs:250-308). Those scenarios depend on the same Windows group-template plumbing this fallback now skips.
  • Recommendation: Do not bypass the grouped wrapper. Preserve TemplatedItemSourceFactory.CreateGrouped(...) / GroupTemplateContext for grouped sources, and instead fix the no-ItemTemplate case lower in the pipeline so group headers/footers continue to function.

Suggestions

  • Add a targeted Windows test for the combination: IsGrouped = true, ItemTemplate = null, and GroupHeaderTemplate and/or GroupFooterTemplate set. The new test page only covers the no-template grouped-items scenario, so it would not catch the regression above.
  • When the description is updated, mention that the fix is Windows handler code plus cross-platform UI snapshots, so reviewers do not misread the added screenshots as cross-platform behavior changes.

Looks Good

  • The PR includes a focused reproduction page and a UI test for the reported issue (Issue23293), which is the right level of coverage for the original bug.
  • The handler change is narrowly scoped to the Windows grouped CollectionView path.

Overall Assessment

The metadata needs a small cleanup, but the larger concern is the Windows grouped-template regression risk. I would not consider this PR ready to merge until the grouped no-ItemTemplate fix preserves GroupTemplateContext behavior for GroupHeaderTemplate / GroupFooterTemplate.

Copy link
Copy Markdown
Contributor

@kubaflo kubaflo left a comment

Choose a reason for hiding this comment

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

Looks like the test is failing

PureWeen pushed a commit that referenced this pull request Mar 23, 2026
#34575)

<!-- Please let the below note in for people that find this PR -->
> [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

## Description

Adds Windows platform support to the `maui-copilot` CI pipeline (AzDO
definition 27723), enabling Copilot PR reviews on Windows-targeted PRs.

### Changes

**`eng/pipelines/ci-copilot.yml`**
- Add `catalyst` and `windows` to Platform parameter values
- Add per-platform pool selection (`androidPool`, `iosPool`, `macPool`,
`windowsPool`)
- Skip Xcode, Android SDK, simulator setup for Windows/Catalyst
- Add Windows-specific "Set screen resolution" step (1920x1080)
- Add MacCatalyst-specific "Disable Notification Center" step
- Fix `sed` command for `Directory.Build.Override.props` on Windows (Git
Bash uses GNU sed)
- Handle Copilot CLI PATH detection on Windows vs Unix
- Change `script:` steps to `bash:` for cross-platform consistency

**`.github/scripts/Review-PR.ps1`**
- Add `catalyst` to ValidateSet for Platform parameter

**`.github/scripts/BuildAndRunHostApp.ps1`**
- Add Windows test assembly directory for artifact collection

**`.github/scripts/post-ai-summary-comment.ps1` /
`post-pr-finalize-comment.ps1`**
- Various improvements for cross-platform comment posting

### Validation

Successfully ran the pipeline with `Platform=windows` on multiple
Windows-specific PRs:
- PR #27713 — ✅ Succeeded
- PR #34337 — ✅ Succeeded
- PR #26217, #27609, #27880, #28617, #29927, #30068 — Triggered and
running

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Mar 29, 2026

🚦 Gate - Test Before and After Fix

📊 Expand Full Gate2b56ab2 · Have updated the test case and have added the iOS snapshot

Gate Result: ❌ FAILED

Platform: WINDOWS · Base: main · Merge base: 720a9d4a

Test Without Fix (expect FAIL) With Fix (expect PASS)
🖥️ Issue23293 Issue23293 ✅ FAIL — 546s ❌ FAIL — 449s
🔴 Without fix — 🖥️ Issue23293: FAIL ✅ · 546s
  Determining projects to restore...
  Restored D:\a\1\s\src\Graphics\src\Graphics.Win2D\Graphics.Win2D.csproj (in 20.98 sec).
  Restored D:\a\1\s\src\Graphics\src\Graphics\Graphics.csproj (in 20.98 sec).
  Restored D:\a\1\s\src\Essentials\src\Essentials.csproj (in 9.36 sec).
  Restored D:\a\1\s\src\Core\src\Core.csproj (in 16.36 sec).
  Restored D:\a\1\s\src\Core\maps\src\Maps.csproj (in 13.9 sec).
  Restored D:\a\1\s\src\Controls\src\Xaml\Controls.Xaml.csproj (in 39 ms).
  Restored D:\a\1\s\src\Controls\src\Core\Controls.Core.csproj (in 36 ms).
  Restored D:\a\1\s\src\Controls\tests\TestCases.HostApp\Controls.TestCases.HostApp.csproj (in 7.01 sec).
  Restored D:\a\1\s\src\Controls\Maps\src\Controls.Maps.csproj (in 12 ms).
  Restored D:\a\1\s\src\Controls\Foldable\src\Controls.Foldable.csproj (in 16 ms).
  Restored D:\a\1\s\src\BlazorWebView\src\Maui\Microsoft.AspNetCore.Components.WebView.Maui.csproj (in 15 ms).
  3 of 14 projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  Graphics -> D:\a\1\s\artifacts\bin\Graphics\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  Essentials -> D:\a\1\s\artifacts\bin\Essentials\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Essentials.dll
  Graphics.Win2D -> D:\a\1\s\artifacts\bin\Graphics.Win2D\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Graphics.Win2D.WinUI.Desktop.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  Core -> D:\a\1\s\artifacts\bin\Core\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.dll
  Controls.BindingSourceGen -> D:\a\1\s\artifacts\bin\Controls.BindingSourceGen\Debug\netstandard2.0\Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  Maps -> D:\a\1\s\artifacts\bin\Maps\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Maps.dll
  Controls.Core -> D:\a\1\s\artifacts\bin\Controls.Core\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  Controls.Xaml -> D:\a\1\s\artifacts\bin\Controls.Xaml\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.Xaml.dll
  Controls.Maps -> D:\a\1\s\artifacts\bin\Controls.Maps\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.Maps.dll
  Controls.Foldable -> D:\a\1\s\artifacts\bin\Controls.Foldable\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.Foldable.dll
  Microsoft.AspNetCore.Components.WebView.Maui -> D:\a\1\s\artifacts\bin\Microsoft.AspNetCore.Components.WebView.Maui\Debug\net10.0-windows10.0.19041.0\Microsoft.AspNetCore.Components.WebView.Maui.dll
  Controls.TestCases.HostApp -> D:\a\1\s\artifacts\bin\Controls.TestCases.HostApp\Debug\net10.0-windows10.0.19041.0\win-x64\Controls.TestCases.HostApp.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:05:43.86
  Determining projects to restore...
  Restored D:\a\1\s\src\TestUtils\src\VisualTestUtils\VisualTestUtils.csproj (in 674 ms).
  Restored D:\a\1\s\src\TestUtils\src\UITest.NUnit\UITest.NUnit.csproj (in 1.53 sec).
  Restored D:\a\1\s\src\TestUtils\src\UITest.Core\UITest.Core.csproj (in 3 ms).
  Restored D:\a\1\s\src\TestUtils\src\UITest.Appium\UITest.Appium.csproj (in 1.48 sec).
  Restored D:\a\1\s\src\TestUtils\src\VisualTestUtils.MagickNet\VisualTestUtils.MagickNet.csproj (in 4.55 sec).
  Restored D:\a\1\s\src\TestUtils\src\UITest.Analyzers\UITest.Analyzers.csproj (in 9.05 sec).
  Restored D:\a\1\s\src\Controls\tests\CustomAttributes\Controls.CustomAttributes.csproj (in 4 ms).
  Restored D:\a\1\s\src\Controls\tests\TestCases.WinUI.Tests\Controls.TestCases.WinUI.Tests.csproj (in 9.04 sec).
  7 of 15 projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  Graphics -> D:\a\1\s\artifacts\bin\Graphics\Debug\net10.0\Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  Essentials -> D:\a\1\s\artifacts\bin\Essentials\Debug\net10.0\Microsoft.Maui.Essentials.dll
  Controls.CustomAttributes -> D:\a\1\s\artifacts\bin\Controls.CustomAttributes\Debug\net10.0\Controls.CustomAttributes.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  Core -> D:\a\1\s\artifacts\bin\Core\Debug\net10.0\Microsoft.Maui.dll
  Controls.Core.Design -> D:\a\1\s\artifacts\bin\Controls.Core.Design\Debug\net472\Microsoft.Maui.Controls.DesignTools.dll
  Controls.BindingSourceGen -> D:\a\1\s\artifacts\bin\Controls.BindingSourceGen\Debug\netstandard2.0\Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  Controls.Core -> D:\a\1\s\artifacts\bin\Controls.Core\Debug\net10.0\Microsoft.Maui.Controls.dll
  UITest.Core -> D:\a\1\s\artifacts\bin\UITest.Core\Debug\net10.0\UITest.Core.dll
  UITest.Appium -> D:\a\1\s\artifacts\bin\UITest.Appium\Debug\net10.0\UITest.Appium.dll
  UITest.NUnit -> D:\a\1\s\artifacts\bin\UITest.NUnit\Debug\net10.0\UITest.NUnit.dll
  VisualTestUtils -> D:\a\1\s\artifacts\bin\VisualTestUtils\Debug\netstandard2.0\VisualTestUtils.dll
  VisualTestUtils.MagickNet -> D:\a\1\s\artifacts\bin\VisualTestUtils.MagickNet\Debug\netstandard2.0\VisualTestUtils.MagickNet.dll
  UITest.Analyzers -> D:\a\1\s\artifacts\bin\UITest.Analyzers\Debug\netstandard2.0\UITest.Analyzers.dll
  Controls.TestCases.WinUI.Tests -> D:\a\1\s\artifacts\bin\Controls.TestCases.WinUI.Tests\Debug\net10.0\Controls.TestCases.WinUI.Tests.dll
Test run for D:\a\1\s\artifacts\bin\Controls.TestCases.WinUI.Tests\Debug\net10.0\Controls.TestCases.WinUI.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (x64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
D:\a\1\s\artifacts\bin\Controls.TestCases.WinUI.Tests\Debug\net10.0\Controls.TestCases.WinUI.Tests.dll
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in D:\a\1\s\artifacts\bin\Controls.TestCases.WinUI.Tests\Debug\net10.0\Controls.TestCases.WinUI.Tests.dll
   NUnit3TestExecutor discovered 1 of 1 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 3/29/2026 7:35:39 PM FixtureSetup for Issue23293(Windows)
>>>>> 3/29/2026 7:35:51 PM GroupedCollectionViewWithoutDataTemplate Start
>>>>> 3/29/2026 7:35:53 PM GroupedCollectionViewWithoutDataTemplate Stop
>>>>> 3/29/2026 7:35:53 PM Log types: 
  Failed GroupedCollectionViewWithoutDataTemplate [2 s]
  Error Message:
   VisualTestUtils.VisualTestFailedException : 
Snapshot different than baseline: GroupedCollectionViewWithoutDataTemplate.png (4.38% difference)
If the correct baseline has changed (this isn't a a bug), then update the baseline image.
See test attachment or download the build artifacts to get the new snapshot file.

More info: https://aka.ms/visual-test-workflow

  Stack Trace:
     at VisualTestUtils.VisualRegressionTester.Fail(String message) in /_/src/TestUtils/src/VisualTestUtils/VisualRegressionTester.cs:line 162
   at VisualTestUtils.VisualRegressionTester.VerifyMatchesSnapshot(String name, ImageSnapshot actualImage, String environmentName, ITestContext testContext) in /_/src/TestUtils/src/VisualTestUtils/VisualRegressionTester.cs:line 123
   at Microsoft.Maui.TestCases.Tests.UITest.<VerifyScreenshot>g__Verify|13_0(String name, <>c__DisplayClass13_0&) in /_/src/Controls/tests/TestCases.Shared.Tests/UITest.cs:line 477
   at Microsoft.Maui.TestCases.Tests.UITest.VerifyScreenshot(String name, Nullable`1 retryDelay, Nullable`1 retryTimeout, Int32 cropLeft, Int32 cropRight, Int32 cropTop, Int32 cropBottom, Double tolerance, Boolean includeTitleBar) in /_/src/Controls/tests/TestCases.Shared.Tests/UITest.cs:line 309
   at Microsoft.Maui.TestCases.Tests.Issues.Issue23293.GroupedCollectionViewWithoutDataTemplate() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue23293.cs:line 18
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

NUnit Adapter 4.5.0.0: Test execution complete
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.09]   Discovering: Controls.TestCases.WinUI.Tests
[xUnit.net 00:00:00.29]   Discovered:  Controls.TestCases.WinUI.Tests

Total tests: 1
     Failed: 1
Test Run Failed.
 Total time: 34.6130 Seconds

🟢 With fix — 🖥️ Issue23293: FAIL ❌ · 449s
  Determining projects to restore...
  All projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  Graphics -> D:\a\1\s\artifacts\bin\Graphics\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  Essentials -> D:\a\1\s\artifacts\bin\Essentials\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  Graphics.Win2D -> D:\a\1\s\artifacts\bin\Graphics.Win2D\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Graphics.Win2D.WinUI.Desktop.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  Core -> D:\a\1\s\artifacts\bin\Core\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.dll
  Controls.BindingSourceGen -> D:\a\1\s\artifacts\bin\Controls.BindingSourceGen\Debug\netstandard2.0\Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  Controls.Core -> D:\a\1\s\artifacts\bin\Controls.Core\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  Maps -> D:\a\1\s\artifacts\bin\Maps\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Maps.dll
  Controls.Xaml -> D:\a\1\s\artifacts\bin\Controls.Xaml\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.Xaml.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  Controls.Foldable -> D:\a\1\s\artifacts\bin\Controls.Foldable\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.Foldable.dll
  Microsoft.AspNetCore.Components.WebView.Maui -> D:\a\1\s\artifacts\bin\Microsoft.AspNetCore.Components.WebView.Maui\Debug\net10.0-windows10.0.19041.0\Microsoft.AspNetCore.Components.WebView.Maui.dll
  Controls.Maps -> D:\a\1\s\artifacts\bin\Controls.Maps\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.Maps.dll
  Controls.TestCases.HostApp -> D:\a\1\s\artifacts\bin\Controls.TestCases.HostApp\Debug\net10.0-windows10.0.19041.0\win-x64\Controls.TestCases.HostApp.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:05:34.36
  Determining projects to restore...
  All projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  Graphics -> D:\a\1\s\artifacts\bin\Graphics\Debug\net10.0\Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  Essentials -> D:\a\1\s\artifacts\bin\Essentials\Debug\net10.0\Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  Core -> D:\a\1\s\artifacts\bin\Core\Debug\net10.0\Microsoft.Maui.dll
  Controls.CustomAttributes -> D:\a\1\s\artifacts\bin\Controls.CustomAttributes\Debug\net10.0\Controls.CustomAttributes.dll
  Controls.Core.Design -> D:\a\1\s\artifacts\bin\Controls.Core.Design\Debug\net472\Microsoft.Maui.Controls.DesignTools.dll
  Controls.BindingSourceGen -> D:\a\1\s\artifacts\bin\Controls.BindingSourceGen\Debug\netstandard2.0\Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684024
  Controls.Core -> D:\a\1\s\artifacts\bin\Controls.Core\Debug\net10.0\Microsoft.Maui.Controls.dll
  UITest.Core -> D:\a\1\s\artifacts\bin\UITest.Core\Debug\net10.0\UITest.Core.dll
  UITest.Appium -> D:\a\1\s\artifacts\bin\UITest.Appium\Debug\net10.0\UITest.Appium.dll
  VisualTestUtils -> D:\a\1\s\artifacts\bin\VisualTestUtils\Debug\netstandard2.0\VisualTestUtils.dll
  UITest.NUnit -> D:\a\1\s\artifacts\bin\UITest.NUnit\Debug\net10.0\UITest.NUnit.dll
  VisualTestUtils.MagickNet -> D:\a\1\s\artifacts\bin\VisualTestUtils.MagickNet\Debug\netstandard2.0\VisualTestUtils.MagickNet.dll
  UITest.Analyzers -> D:\a\1\s\artifacts\bin\UITest.Analyzers\Debug\netstandard2.0\UITest.Analyzers.dll
  Controls.TestCases.WinUI.Tests -> D:\a\1\s\artifacts\bin\Controls.TestCases.WinUI.Tests\Debug\net10.0\Controls.TestCases.WinUI.Tests.dll
Test run for D:\a\1\s\artifacts\bin\Controls.TestCases.WinUI.Tests\Debug\net10.0\Controls.TestCases.WinUI.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (x64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
D:\a\1\s\artifacts\bin\Controls.TestCases.WinUI.Tests\Debug\net10.0\Controls.TestCases.WinUI.Tests.dll
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in D:\a\1\s\artifacts\bin\Controls.TestCases.WinUI.Tests\Debug\net10.0\Controls.TestCases.WinUI.Tests.dll
   NUnit3TestExecutor discovered 1 of 1 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 3/29/2026 7:43:09 PM FixtureSetup for Issue23293(Windows)
>>>>> 3/29/2026 7:43:21 PM GroupedCollectionViewWithoutDataTemplate Start
>>>>> 3/29/2026 7:43:23 PM GroupedCollectionViewWithoutDataTemplate Stop
>>>>> 3/29/2026 7:43:23 PM Log types: 
  Failed GroupedCollectionViewWithoutDataTemplate [2 s]
  Error Message:
   VisualTestUtils.VisualTestFailedException : 
Snapshot different than baseline: GroupedCollectionViewWithoutDataTemplate.png (4.08% difference)
If the correct baseline has changed (this isn't a a bug), then update the baseline image.
See test attachment or download the build artifacts to get the new snapshot file.

More info: https://aka.ms/visual-test-workflow

  Stack Trace:
     at VisualTestUtils.VisualRegressionTester.Fail(String message) in /_/src/TestUtils/src/VisualTestUtils/VisualRegressionTester.cs:line 162
   at VisualTestUtils.VisualRegressionTester.VerifyMatchesSnapshot(String name, ImageSnapshot actualImage, String environmentName, ITestContext testContext) in /_/src/TestUtils/src/VisualTestUtils/VisualRegressionTester.cs:line 123
   at Microsoft.Maui.TestCases.Tests.UITest.<VerifyScreenshot>g__Verify|13_0(String name, <>c__DisplayClass13_0&) in /_/src/Controls/tests/TestCases.Shared.Tests/UITest.cs:line 477
   at Microsoft.Maui.TestCases.Tests.UITest.VerifyScreenshot(String name, Nullable`1 retryDelay, Nullable`1 retryTimeout, Int32 cropLeft, Int32 cropRight, Int32 cropTop, Int32 cropBottom, Double tolerance, Boolean includeTitleBar) in /_/src/Controls/tests/TestCases.Shared.Tests/UITest.cs:line 309
   at Microsoft.Maui.TestCases.Tests.Issues.Issue23293.GroupedCollectionViewWithoutDataTemplate() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue23293.cs:line 18
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

NUnit Adapter 4.5.0.0: Test execution complete
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.09]   Discovering: Controls.TestCases.WinUI.Tests
[xUnit.net 00:00:00.29]   Discovered:  Controls.TestCases.WinUI.Tests

Total tests: 1
Test Run Failed.
     Failed: 1
 Total time: 26.3397 Seconds

⚠️ Issues found
  • Issue23293 FAILED with fix (should pass)
    • GroupedCollectionViewWithoutDataTemplate [2 s]
    • VisualTestUtils.VisualTestFailedException : Snapshot different than baseline: GroupedCollectionViewWithoutDataTemplate.png (4.08% difference) If the correct baseline has changed (this isn't a a bug...
📁 Fix files reverted (2 files)
  • eng/pipelines/ci-copilot.yml
  • src/Controls/src/Core/Handlers/Items/GroupableItemsViewHandler.Windows.cs

@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Mar 29, 2026

🤖 AI Summary

📊 Expand Full Review2b56ab2 · Have updated the test case and have added the iOS snapshot
🔍 Pre-Flight — Context & Validation

Issue: #23293 - [MAUI] I6 Grouping - 'Grouping for Vertical list without DataTemplates' page loading exception
PR: #28617 - [Windows] Fix for Grouping collection view without data template results in displaying the default string representation of the object
Platforms Affected: Windows (primary), validated on Android, iOS, Mac
Files Changed: 1 implementation, 2 test, 4 snapshots

Key Findings

  • When IsGrouped=true and no ItemTemplate is specified, the original code always called TemplatedItemSourceFactory.CreateGrouped(), which wraps items in GroupTemplateContext objects. Without a DataTemplate to unwrap them, WinUI CollectionView falls back to .ToString() on those wrappers.
  • PR's fix branches on itemTemplate is not null && itemsSource is not null: if template is present, use the full TemplatedItemSourceFactory.CreateGrouped() path; otherwise use itemsSource directly as CollectionViewSource.Source.
  • Potential concern (raised in review): When itemsSource is null, CreateDefaultGroupedCollectionViewSource(null) is still called, creating a CollectionViewSource with Source = null. Reviewer @rmarinho asked about this; author noted a related PR ([Windows] Fixed the EmptyView and EmptyViewTemplate issues in CollectionView #28472) removes the null check upstream.
  • The CreateDefaultGroupedCollectionViewSource path does NOT set ItemsPath, which means group header/footer templates won't get the Items property — this could break GroupHeaderTemplate/GroupFooterTemplate when no ItemTemplate is set.
  • Gate result: ❌ FAILED — tests did NOT behave as expected on Windows with this fix.
  • Prior agent review found on PR: yes (labels: s/agent-changes-requested, s/agent-gate-failed, s/agent-fix-win).
  • Test type: UITest (screenshot verification), Category=CollectionView, FullyQualifiedName~Issue23293

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #28617 Branch on itemTemplate != null: use templated path vs direct source ❌ FAILED (Gate) GroupableItemsViewHandler.Windows.cs Doesn't handle null itemsSource; may break GroupHeader/FooterTemplate

🔧 Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix Modify GroupedItemTemplateCollection.CreateGroupTemplateContext() to skip wrapping items in ItemTemplateContext when _itemTemplate is null; pass raw items directly to GroupTemplateContext.Items ✅ PASS GroupedItemTemplateCollection.cs (+3 lines) More surgical — keeps grouped infrastructure intact; preserves GroupHeader/Footer support
2 try-fix Null-template short-circuit in TemplatedItemSourceFactory.Create — return itemsSource directly when itemTemplate == null, no wrapping ✅ PASS TemplatedItemSourceFactory.cs (+3 lines) Lowest-level fix; keeps GroupTemplateContext/ItemsPath infrastructure; changes behavior for all callers
3 try-fix Modified GroupTemplateContext to project items through unwrapping enumerable to expose raw Item values when no template ❌ FAIL GroupTemplateContext.cs Group headers still showed GroupTemplateContext.ToString() — 4.08% screenshot mismatch
4 try-fix Handler/style layer — DisplayMemberPath + default group-header template when GroupHeaderTemplate is null ❌ FAIL GroupableItemsViewHandler.Windows.cs, GroupHeaderStyleSelector.cs, ItemsViewStyles.xaml Page source fixed but header still showed GroupTemplateContext.ToString() (4.08% diff)
PR PR #28617 Branch on (itemTemplate != null && itemsSource != null) in handler: bypass grouped infrastructure ❌ FAILED (Gate) GroupableItemsViewHandler.Windows.cs Gate failed on Windows

Cross-Pollination

Model Round New Ideas? Details
claude-opus-4.6 2 No All architectural layers covered; no untried approaches identified

Exhausted: Yes
Selected Fix: Candidate #1 (claude-opus-4.6) — ✅ PASS, modifies GroupedItemTemplateCollection.CreateGroupTemplateContext() to skip wrapping when _itemTemplate == null. Most targeted fix: only affects grouped path, preserves GroupHeader/Footer template support, minimal change (+3 lines in one file). Candidate #2 also passes but modifies a more general-purpose factory method.


📋 Report — Final Recommendation

⚠️ Final Recommendation: REQUEST CHANGES

Phase Status

Phase Status Notes
Pre-Flight ✅ COMPLETE Issue #23293, Windows grouped CollectionView without DataTemplate
Gate ❌ FAILED Windows — tests did not behave as expected
Try-Fix ✅ COMPLETE 4 attempts, 2 passing
Report ✅ COMPLETE

Summary

PR #28617 fixes a Windows-only bug where a grouped CollectionView with IsGrouped=true but no ItemTemplate displays the default .ToString() of internal wrapper objects (ItemTemplateContext) instead of actual data. The PR's fix in GroupableItemsViewHandler.Windows.cs is architecturally incorrect and failed the gate test. The Try-Fix phase found two better, more targeted fixes — the best is a 3-line change in GroupedItemTemplateCollection.cs.

Additionally, the HostApp test (Issue23293.cs) only creates 1 group with 1 item, but the committed snapshot appears to show 5 groups × 5 items — a mismatch that independently causes screenshot comparison failure.

Root Cause

When IsGrouped=true and no ItemTemplate is set, GroupableItemsViewHandler.Windows.cs calls TemplatedItemSourceFactory.CreateGrouped() which creates a GroupedItemTemplateCollection. Inside, each group's items are wrapped in ItemTemplateContext objects via TemplatedItemSourceFactory.Create(). With ItemsPath = "Items" on the CollectionViewSource, WinUI reads GroupTemplateContext.Items (the wrapped contexts). Since ListViewBase.ItemTemplate = null (no template), WinUI falls back to calling .ToString() on the ItemTemplateContext wrapper objects — not the actual data items.

Fix Quality

PR's Fix (❌ FAILED): Branches on (itemTemplate != null && itemsSource != null) in the handler. When false, creates a plain CollectionViewSource bypassing the GroupedItemTemplateCollection/GroupTemplateContext/ItemsPath infrastructure entirely. Problems:

  1. When itemsSource is null, still calls CreateDefaultGroupedCollectionViewSource(null) creating a CollectionViewSource with null Source
  2. The default path does not set ItemsPath, breaking GroupHeader/Footer template support when they ARE set but ItemTemplate is not
  3. Gate test failed — likely also caused by test data mismatch in Issue23293.cs

Candidate #1 — Best Fix (✅ PASSED):
Modify GroupedItemTemplateCollection.CreateGroupTemplateContext() to check _itemTemplate != null before wrapping items in ItemTemplateContext. When null, pass the raw group directly as GroupTemplateContext.Items.

- var groupItemsList = TemplatedItemSourceFactory.Create(group as IEnumerable, _itemTemplate, _container, mauiContext: _mauiContext);
+ var groupItemsList = _itemTemplate != null
+     ? TemplatedItemSourceFactory.Create(group as IEnumerable, _itemTemplate, _container, mauiContext: _mauiContext)
+     : group;

✅ Keeps grouped infrastructure intact (GroupedItemTemplateCollection, GroupTemplateContext, ItemsPath)
✅ Preserves GroupHeader/Footer template support
✅ Only affects grouped path, not non-grouped
✅ Minimal: +3 lines in 1 file

Candidate #2 (✅ PASSED): Early-return in TemplatedItemSourceFactory.Create() when itemTemplate == null — also works but modifies a more general-purpose factory method, potentially affecting other callers.

Requested Changes

  1. Replace the handler fix in GroupableItemsViewHandler.Windows.cs with the fix in GroupedItemTemplateCollection.cs (Candidate [Draft] Readme WIP #1). Revert the handler changes (CreateGroupedCollectionViewSource / CreateDefaultGroupedCollectionViewSource) and instead fix GroupedItemTemplateCollection.CreateGroupTemplateContext().

  2. Fix the HostApp test data in Issue23293.cs — update CreateAnimalsCollection() to match what was actually committed as the snapshot (5 groups × 5 animals), or regenerate the snapshot to match the current test data (1 group, 1 item).

  3. Address the null itemsSource question raised by reviewer @rmarinho — the PR should explicitly document or guard against the itemsSource = null case in the new CreateDefaultGroupedCollectionViewSource (even if that path is no longer needed after adopting the better fix).


Copy link
Copy Markdown
Contributor

@kubaflo kubaflo 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 is failing

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 platform/windows s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-win AI found a better alternative fix than the PR s/agent-gate-failed AI could not verify tests catch the bug s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[MAUI] I6 Grouping - 'Grouping for Vertical list without DataTemplates' page loading exception

9 participants