[Windows] Fix for Grouping collection view without data template results in displaying the default string representation of the object#28617
Conversation
|
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. |
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
| IsSourceGrouped = true, | ||
| ItemsPath = new Microsoft.UI.Xaml.PropertyPath(nameof(GroupTemplateContext.Items)) | ||
| }; | ||
| return new CollectionViewSource |
There was a problem hiding this comment.
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);
There was a problem hiding this comment.
@jsuarezruiz , As suggested have encapsulated the logic within separate methods for better readability.
| public void GroupedCollectionViewWithoutDataTemplate() | ||
| { | ||
| App.WaitForElement("CollectionViewWithoutDataTemplate"); | ||
| VerifyScreenshot(); |
There was a problem hiding this comment.
@jsuarezruiz , I have committed the snapshots.
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
| } | ||
| } | ||
|
|
||
| private CollectionViewSource CreateGroupedCollectionViewSource(IEnumerable itemsSource, DataTemplate itemTemplate) |
There was a problem hiding this comment.
Can we drop private we don t use it in our code base
There was a problem hiding this comment.
@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) |
There was a problem hiding this comment.
| private CollectionViewSource CreateDefaultGroupedCollectionViewSource(IEnumerable itemsSource) | |
| CollectionViewSource CreateDefaultGroupedCollectionViewSource(IEnumerable itemsSource) |
There was a problem hiding this comment.
@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) |
There was a problem hiding this comment.
What happens if itemsSource is null?
There was a problem hiding this comment.
|
/azp run MAUI-UITests-public |
|
Azure Pipelines successfully started running 1 pipeline(s). |
…plates' page loading exception ).
…plates' page loading exception ).
…plates' page loading exception ).
…plates' page loading exception ).
…plates' page loading exception ).
…plates' page loading exception ).
…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)
e70284c to
2b56ab2
Compare
There was a problem hiding this comment.
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 |
🤖 AI Summary📊 Expand Full Review —
|
| # | 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.GroupedCollectionViewWithoutDataTemplatefailed 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 Fixedstructure 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
itemsSourcewhenitemTemplateis 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 bypassesTemplatedItemSourceFactory.CreateGrouped(...)and returns the raw grouped source directly whenItemTemplateis null. - Why this matters: On Windows, grouped rendering relies on
GroupTemplateContextfor group metadata.GroupedItemTemplateCollectioncreates that wrapper and populatesHeaderItemTemplateContext/FooterItemTemplateContext(src/Controls/src/Core/Platform/Windows/CollectionView/GroupedItemTemplateCollection.cs,GroupTemplateContext.cs). The Windows group header template then binds itsDataContexttoHeaderItemTemplateContext(src/Controls/src/Core/Platform/Windows/CollectionView/ItemsViewStyles.xaml). If the source is raw groups instead ofGroupTemplateContext,GroupHeaderTemplate/GroupFooterTemplatecannot 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(...)/GroupTemplateContextfor grouped sources, and instead fix the no-ItemTemplatecase lower in the pipeline so group headers/footers continue to function.
Suggestions
- Add a targeted Windows test for the combination:
IsGrouped = true,ItemTemplate = null, andGroupHeaderTemplateand/orGroupFooterTemplateset. 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
left a comment
There was a problem hiding this comment.
Could you please apply the AI's suggestions?
🤖 AI Summary📊 Expand Full Review —
|
| # | 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
ItemTemplateshow 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
itemsSourceis null, and the author answered that the new fallback path can create a groupedCollectionViewSourcewith a nullSourceif 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, ands/agent-fix-winoutcome.
Edge Cases Mentioned
itemsSource == nullon 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.GroupedCollectionViewWithoutDataTemplatefailed 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
- Imported from prior PR agent review summary already posted on PR [Windows] Fix for Grouping collection view without data template results in displaying the default string representation of the object #28617.
- Without the PR fix,
Issue23293.GroupedCollectionViewWithoutDataTemplatefailed 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
Result: FAILED
Gate Result: FAILED
Platform: windows
Mode: Full Verification
- Tests FAIL without fix:
- Tests PASS with fix:
Notes
- Without the PR fix,
Issue23293.GroupedCollectionViewWithoutDataTemplatefailed 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
- Imported from prior PR agent review summary already posted on PR [Windows] Fix for Grouping collection view without data template results in displaying the default string representation of the object #28617.
📋 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 Fixedstructure 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
itemsSourcewhenitemTemplateis 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 bypassesTemplatedItemSourceFactory.CreateGrouped(...)and returns the raw grouped source directly whenItemTemplateis null. - Why this matters: On Windows, grouped rendering relies on
GroupTemplateContextfor group metadata.GroupedItemTemplateCollectioncreates that wrapper and populatesHeaderItemTemplateContext/FooterItemTemplateContext(src/Controls/src/Core/Platform/Windows/CollectionView/GroupedItemTemplateCollection.cs,GroupTemplateContext.cs). The Windows group header template then binds itsDataContexttoHeaderItemTemplateContext(src/Controls/src/Core/Platform/Windows/CollectionView/ItemsViewStyles.xaml). If the source is raw groups instead ofGroupTemplateContext,GroupHeaderTemplate/GroupFooterTemplatecannot 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(...)/GroupTemplateContextfor grouped sources, and instead fix the no-ItemTemplatecase lower in the pipeline so group headers/footers continue to function.
Suggestions
- Add a targeted Windows test for the combination:
IsGrouped = true,ItemTemplate = null, andGroupHeaderTemplateand/orGroupFooterTemplateset. 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
left a comment
There was a problem hiding this comment.
Looks like the test is failing
#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>
🚦 Gate - Test Before and After Fix📊 Expand Full Gate —
|
| 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.ymlsrc/Controls/src/Core/Handlers/Items/GroupableItemsViewHandler.Windows.cs
🤖 AI Summary📊 Expand Full Review —
|
| # | 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:
- When
itemsSourceis null, still callsCreateDefaultGroupedCollectionViewSource(null)creating aCollectionViewSourcewith null Source - The default path does not set
ItemsPath, breaking GroupHeader/Footer template support when they ARE set but ItemTemplate is not - 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
-
Replace the handler fix in
GroupableItemsViewHandler.Windows.cswith the fix inGroupedItemTemplateCollection.cs(Candidate [Draft] Readme WIP #1). Revert the handler changes (CreateGroupedCollectionViewSource/CreateDefaultGroupedCollectionViewSource) and instead fixGroupedItemTemplateCollection.CreateGroupTemplateContext(). -
Fix the HostApp test data in
Issue23293.cs— updateCreateAnimalsCollection()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). -
Address the null
itemsSourcequestion raised by reviewer @rmarinho — the PR should explicitly document or guard against theitemsSource = nullcase in the newCreateDefaultGroupedCollectionViewSource(even if that path is no longer needed after adopting the better fix).

Issue Details
Root Cause
Description of Change
Validated the behaviour in the following platforms
Issues Fixed
Fixes #23293
Output
Before.mp4
After.mp4