[Windows] FlyoutPage: update CollapseStyle at runtime#29927
[Windows] FlyoutPage: update CollapseStyle at runtime#29927kubaflo merged 12 commits intodotnet:inflight/currentfrom
Conversation
|
Hey there @@devanathan-vaithiyanathan! 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 MAUI-UITests-public |
|
Azure Pipelines successfully started running 1 pipeline(s). |
| @@ -0,0 +1,29 @@ | |||
| # if TEST_FAILS_ON_ANDROID && TEST_FAILS_ON_CATALYST && TEST_FAILS_ON_IOS // It's a Windows specific API issue, so restricting the other platforms | |||
There was a problem hiding this comment.
Because is a platform specific, here can use directly #if WINDOWS. Are not failing on other platforms, just have not sense.
There was a problem hiding this comment.
@jsuarezruiz , Thanks for pointing out. I have modified the changes
a39ee9a to
a1ad2f8
Compare
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 29927Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 29927" |
There was a problem hiding this comment.
Pull request overview
This PR fixes a Windows-specific issue where changing the CollapseStyle property on a FlyoutPage at runtime had no effect. The fix enables dynamic updates to the flyout pane's collapse behavior by adding a property changed callback and mapper implementation.
Key Changes
- Added runtime support for
CollapseStyleproperty changes in Windows FlyoutPage - Implemented property change notification system via
OnCollapseStylePropertyChanged - Added Windows-specific mapper logic to translate
CollapseStylevalues to WinUIPaneDisplayMode
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| src/Controls/src/Core/PlatformConfiguration/WindowsSpecific/FlyoutPage.cs | Added propertyChanged callback to CollapseStyleProperty to trigger handler updates when value changes at runtime |
| src/Controls/src/Core/FlyoutPage/FlyoutPage.Mapper.cs | Added Windows-specific mapper for CollapseStyleProperty that sets WinUI NavigationView.PaneDisplayMode based on CollapseStyle value |
| src/Controls/tests/TestCases.HostApp/Issues/Issue18200.cs | Created test page demonstrating dynamic CollapseStyle switching with button toggle functionality |
| src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18200.cs | Added UI test to verify flyout collapse behavior changes when CollapseStyle is toggled |
| @@ -0,0 +1,79 @@ | |||
| using Microsoft.Maui.Controls.PlatformConfiguration; | |||
| using Microsoft.Maui.Controls.PlatformConfiguration.WindowsSpecific; | |||
There was a problem hiding this comment.
There's an extra space in the using statement that creates inconsistent formatting with other using statements in the file.
| using Microsoft.Maui.Controls.PlatformConfiguration.WindowsSpecific; | |
| using Microsoft.Maui.Controls.PlatformConfiguration.WindowsSpecific; |
|
|
||
| namespace Maui.Controls.Sample.Issues; | ||
|
|
||
| [Issue(IssueTracker.Github, 18200, "Flyout Page SetCollapseStyle doesn't have any change", PlatformAffected.UWP)] |
There was a problem hiding this comment.
The PlatformAffected.UWP value is outdated. MAUI uses Windows (WinUI3) instead of UWP (Universal Windows Platform). This should be PlatformAffected.Windows or simply PlatformAffected.All if testing on all platforms is acceptable.
| [Issue(IssueTracker.Github, 18200, "Flyout Page SetCollapseStyle doesn't have any change", PlatformAffected.UWP)] | |
| [Issue(IssueTracker.Github, 18200, "Flyout Page SetCollapseStyle doesn't have any change", PlatformAffected.Windows)] |
| { | ||
| this.On<Microsoft.Maui.Controls.PlatformConfiguration.Windows>().SetCollapseStyle(CollapseStyle.Partial); | ||
|
|
||
| // Set the flyout page properties | ||
| FlyoutLayoutBehavior = FlyoutLayoutBehavior.Popover; | ||
|
|
||
| // Create the flyout content | ||
| var flyoutPage = new ContentPage | ||
| { | ||
| Title = "Master", | ||
| BackgroundColor = Colors.Blue | ||
| }; | ||
|
|
||
| var page1Button = new Button | ||
| { | ||
| Text = "Page1", | ||
| AutomationId = "FlyoutItem", | ||
| HorizontalOptions = LayoutOptions.Start, | ||
| VerticalOptions = LayoutOptions.Center | ||
| }; | ||
|
|
||
| flyoutPage.Content = new VerticalStackLayout | ||
| { | ||
| Children = { page1Button } | ||
| }; | ||
|
|
||
| // Create the detail content | ||
| var detailPage = new ContentPage | ||
| { | ||
| Title = "Detail", | ||
| BackgroundColor = Colors.LightYellow | ||
| }; | ||
|
|
||
| _button = new Button | ||
| { | ||
| Text = "Change Collapse Style", | ||
| AutomationId = "CollapseStyleButton", | ||
| }; | ||
| _button.Clicked += OnCollapseStyleValueChanged; | ||
|
|
||
| detailPage.Content = new VerticalStackLayout | ||
| { | ||
| Children = { | ||
| new Microsoft.Maui.Controls.Label | ||
| { | ||
| Text = "Welcome to .NET MAUI!", | ||
| TextColor = Colors.Black, | ||
| HorizontalOptions = LayoutOptions.Center, | ||
| VerticalOptions = LayoutOptions.Center | ||
| }, | ||
| _button | ||
| } | ||
| }; | ||
|
|
||
| // Set the flyout and detail pages | ||
| Flyout = flyoutPage; | ||
| Detail = detailPage; | ||
| } | ||
|
|
||
| void OnCollapseStyleValueChanged(object sender, EventArgs e) | ||
| { | ||
| var currentCollapseStyle = this.On<Microsoft.Maui.Controls.PlatformConfiguration.Windows>().GetCollapseStyle(); | ||
| var newCollapseStyle = currentCollapseStyle == CollapseStyle.Full | ||
| ? CollapseStyle.Partial | ||
| : CollapseStyle.Full; | ||
|
|
||
| this.On<Microsoft.Maui.Controls.PlatformConfiguration.Windows>().SetCollapseStyle(newCollapseStyle); | ||
| } |
There was a problem hiding this comment.
[nitpick] According to the MAUI coding guidelines, file indentation should use tabs, but this file uses spaces for indentation (4 spaces). While this might be consistent within the immediate context, the repository standard is to use tabs. Consider running dotnet format to ensure consistent formatting.
| { | |
| this.On<Microsoft.Maui.Controls.PlatformConfiguration.Windows>().SetCollapseStyle(CollapseStyle.Partial); | |
| // Set the flyout page properties | |
| FlyoutLayoutBehavior = FlyoutLayoutBehavior.Popover; | |
| // Create the flyout content | |
| var flyoutPage = new ContentPage | |
| { | |
| Title = "Master", | |
| BackgroundColor = Colors.Blue | |
| }; | |
| var page1Button = new Button | |
| { | |
| Text = "Page1", | |
| AutomationId = "FlyoutItem", | |
| HorizontalOptions = LayoutOptions.Start, | |
| VerticalOptions = LayoutOptions.Center | |
| }; | |
| flyoutPage.Content = new VerticalStackLayout | |
| { | |
| Children = { page1Button } | |
| }; | |
| // Create the detail content | |
| var detailPage = new ContentPage | |
| { | |
| Title = "Detail", | |
| BackgroundColor = Colors.LightYellow | |
| }; | |
| _button = new Button | |
| { | |
| Text = "Change Collapse Style", | |
| AutomationId = "CollapseStyleButton", | |
| }; | |
| _button.Clicked += OnCollapseStyleValueChanged; | |
| detailPage.Content = new VerticalStackLayout | |
| { | |
| Children = { | |
| new Microsoft.Maui.Controls.Label | |
| { | |
| Text = "Welcome to .NET MAUI!", | |
| TextColor = Colors.Black, | |
| HorizontalOptions = LayoutOptions.Center, | |
| VerticalOptions = LayoutOptions.Center | |
| }, | |
| _button | |
| } | |
| }; | |
| // Set the flyout and detail pages | |
| Flyout = flyoutPage; | |
| Detail = detailPage; | |
| } | |
| void OnCollapseStyleValueChanged(object sender, EventArgs e) | |
| { | |
| var currentCollapseStyle = this.On<Microsoft.Maui.Controls.PlatformConfiguration.Windows>().GetCollapseStyle(); | |
| var newCollapseStyle = currentCollapseStyle == CollapseStyle.Full | |
| ? CollapseStyle.Partial | |
| : CollapseStyle.Full; | |
| this.On<Microsoft.Maui.Controls.PlatformConfiguration.Windows>().SetCollapseStyle(newCollapseStyle); | |
| } | |
| { | |
| this.On<Microsoft.Maui.Controls.PlatformConfiguration.Windows>().SetCollapseStyle(CollapseStyle.Partial); | |
| // Set the flyout page properties | |
| FlyoutLayoutBehavior = FlyoutLayoutBehavior.Popover; | |
| // Create the flyout content | |
| var flyoutPage = new ContentPage | |
| { | |
| Title = "Master", | |
| BackgroundColor = Colors.Blue | |
| }; | |
| var page1Button = new Button | |
| { | |
| Text = "Page1", | |
| AutomationId = "FlyoutItem", | |
| HorizontalOptions = LayoutOptions.Start, | |
| VerticalOptions = LayoutOptions.Center | |
| }; | |
| flyoutPage.Content = new VerticalStackLayout | |
| { | |
| Children = { page1Button } | |
| }; | |
| // Create the detail content | |
| var detailPage = new ContentPage | |
| { | |
| Title = "Detail", | |
| BackgroundColor = Colors.LightYellow | |
| }; | |
| _button = new Button | |
| { | |
| Text = "Change Collapse Style", | |
| AutomationId = "CollapseStyleButton", | |
| }; | |
| _button.Clicked += OnCollapseStyleValueChanged; | |
| detailPage.Content = new VerticalStackLayout | |
| { | |
| Children = { | |
| new Microsoft.Maui.Controls.Label | |
| { | |
| Text = "Welcome to .NET MAUI!", | |
| TextColor = Colors.Black, | |
| HorizontalOptions = LayoutOptions.Center, | |
| VerticalOptions = LayoutOptions.Center | |
| }, | |
| _button | |
| } | |
| }; | |
| // Set the flyout and detail pages | |
| Flyout = flyoutPage; | |
| Detail = detailPage; | |
| } | |
| void OnCollapseStyleValueChanged(object sender, EventArgs e) | |
| { | |
| var currentCollapseStyle = this.On<Microsoft.Maui.Controls.PlatformConfiguration.Windows>().GetCollapseStyle(); | |
| var newCollapseStyle = currentCollapseStyle == CollapseStyle.Full | |
| ? CollapseStyle.Partial | |
| : CollapseStyle.Full; | |
| this.On<Microsoft.Maui.Controls.PlatformConfiguration.Windows>().SetCollapseStyle(newCollapseStyle); | |
| } |
| var flyoutLayoutBehavior = (view as FlyoutPage)?.FlyoutLayoutBehavior; | ||
| if (view is BindableObject bindable && handler.PlatformView is Microsoft.Maui.Platform.RootNavigationView navigationView && flyoutLayoutBehavior is FlyoutLayoutBehavior.Popover) | ||
| { | ||
| var collapseStyle = PlatformConfiguration.WindowsSpecific.FlyoutPage.GetCollapseStyle(bindable); | ||
| switch (collapseStyle) | ||
| { | ||
| case PlatformConfiguration.WindowsSpecific.CollapseStyle.Partial: | ||
| navigationView.PaneDisplayMode = Microsoft.UI.Xaml.Controls.NavigationViewPaneDisplayMode.LeftCompact; | ||
| break; | ||
| case PlatformConfiguration.WindowsSpecific.CollapseStyle.Full: | ||
| default: | ||
| navigationView.PaneDisplayMode = Microsoft.UI.Xaml.Controls.NavigationViewPaneDisplayMode.LeftMinimal; | ||
| break; | ||
| } | ||
| } |
There was a problem hiding this comment.
The pattern used here differs from the iOS platform-specific properties. Looking at the iOS PrefersHomeIndicatorAutoHiddenProperty and PrefersStatusBarHiddenProperty implementations in FlyoutPage.Mapper.cs, those mappers simply call handler.UpdateValue() to trigger the handler's mapper logic.
However, this implementation directly manipulates the PaneDisplayMode property inside MapCollapseStyle. While this works, it bypasses the normal mapper flow and could lead to inconsistencies if UpdatePaneDisplayModeFromFlyoutBehavior is called elsewhere (e.g., when FlyoutBehavior changes), which would reset PaneDisplayMode to LeftMinimal regardless of the CollapseStyle setting.
Consider integrating the CollapseStyle logic into UpdatePaneDisplayModeFromFlyoutBehavior in MauiNavigationView.cs so that it considers both FlyoutBehavior and CollapseStyle when determining the correct PaneDisplayMode. This would ensure the CollapseStyle is respected even when FlyoutBehavior changes at runtime.
| var flyoutLayoutBehavior = (view as FlyoutPage)?.FlyoutLayoutBehavior; | |
| if (view is BindableObject bindable && handler.PlatformView is Microsoft.Maui.Platform.RootNavigationView navigationView && flyoutLayoutBehavior is FlyoutLayoutBehavior.Popover) | |
| { | |
| var collapseStyle = PlatformConfiguration.WindowsSpecific.FlyoutPage.GetCollapseStyle(bindable); | |
| switch (collapseStyle) | |
| { | |
| case PlatformConfiguration.WindowsSpecific.CollapseStyle.Partial: | |
| navigationView.PaneDisplayMode = Microsoft.UI.Xaml.Controls.NavigationViewPaneDisplayMode.LeftCompact; | |
| break; | |
| case PlatformConfiguration.WindowsSpecific.CollapseStyle.Full: | |
| default: | |
| navigationView.PaneDisplayMode = Microsoft.UI.Xaml.Controls.NavigationViewPaneDisplayMode.LeftMinimal; | |
| break; | |
| } | |
| } | |
| handler.UpdateValue(nameof(IFlyoutView.FlyoutBehavior)); |
| @@ -0,0 +1,29 @@ | |||
| # if WINDOWS // It's a Windows specific API issue, so restricting the other platforms | |||
There was a problem hiding this comment.
According to the UI Testing Guidelines, platform-specific tests using #if directives should only be used when there's a specific technical limitation. The comment indicates this is a "Windows specific API issue", but CollapseStyle is designed to only affect Windows. Consider whether the test should still run on other platforms (where it would simply not test the CollapseStyle behavior) to ensure the FlyoutPage doesn't break on other platforms when the API is called. If this is truly Windows-only due to the API being Windows-specific by design (not a bug), the current approach is acceptable, but the comment should clarify this is by design, not a limitation.
| public void VerifyFlyoutCollapseStyleBehaviorChanges() | ||
| { | ||
| App.WaitForElement("CollapseStyleButton"); | ||
| App.Tap("CollapseStyleButton"); | ||
| App.TapFlyoutPageIcon(); | ||
| App.TapFlyoutPageIcon(); // Close the flyout | ||
| App.WaitForNoElement("FlyoutItem"); | ||
| App.Tap("CollapseStyleButton"); | ||
| App.WaitForElement("FlyoutItem"); | ||
| } |
There was a problem hiding this comment.
The test logic has a potential issue: Line 24 waits for "FlyoutItem" to not be present after setting CollapseStyle to Full and tapping twice (open/close). However, in Full collapse mode with a Popover layout, the flyout should be minimally collapsed and still closeable. The test then expects "FlyoutItem" to be visible again after switching back to Partial at line 26, but this seems to test visibility rather than the collapse style behavior.
Consider enhancing the test to verify the actual visual behavior difference between Full and Partial collapse styles, not just whether items are visible after opening/closing. The current test might pass even if CollapseStyle changes aren't working correctly, as long as the flyout opens and closes.
🤖 AI Summary📊 Expand Full Review —
|
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #29927 | Trigger handler updates when CollapseStyle changes, then map Windows CollapseStyle values to WinUI PaneDisplayMode at runtime |
PENDING (Gate) | src/Controls/src/Core/FlyoutPage/FlyoutPage.Mapper.cs, src/Controls/src/Core/PlatformConfiguration/WindowsSpecific/FlyoutPage.cs, src/Controls/tests/TestCases.HostApp/Issues/Issue18200.cs, src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18200.cs |
Original PR |
🚦 Gate — Test Verification
Result: PASSED
Gate Result: PASSED
Platform: windows
Mode: Full Verification
- Tests FAIL without fix:
- Tests PASS with fix:
Notes
- Verification used
Issue18200on Windows. - Without the fix, the UI test timed out waiting for the flyout item state change, reproducing the bug.
- With the fix applied, the same test passed, confirming the PR resolves the runtime collapse-style update issue.
🔧 Fix — Analysis & Comparison
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| 1 | try-fix | Route CollapseStyle through MauiNavigationView's flyout-behavior pipeline using a pane-display-mode override instead of mutating PaneDisplayMode directly in the mapper |
PASS | 3 files | Robust against later FlyoutBehavior updates overwriting the collapse style |
| 2 | try-fix | Use a virtual flyout-pane-display-mode hook in MauiNavigationView/RootNavigationView so UpdatePaneDisplayModeFromFlyoutBehavior natively resolves compact vs minimal mode |
PASS | 4 files | Template-method style alternative that keeps collapse-style behavior inside the existing pipeline |
| 3 | try-fix | Reuse existing PinPaneDisplayModeTo support on RootNavigationView, set it from the new CollapseStyle mapper, then re-run IFlyoutView.FlyoutBehavior mapping |
PASS | 2 files | Smallest passing alternative before cross-pollination; leans on existing navigation-view behavior |
| 4 | try-fix | Use a Windows resource flag on the navigation view and let MauiNavigationView re-evaluate flyout behavior against that flag when CollapseStyle changes |
PASS | 2 files | Passes, but relies on a string-keyed resource flag and removes an existing flyout-behavior cache guard |
| 5 | try-fix | Wrap the existing Windows FlyoutBehavior mapper with ModifyMapping, then apply CollapseStyle after the base mapper runs and re-trigger via UpdateValue(FlyoutBehavior) on property change |
PASS | 2 files | Simplest robust passing option; keeps the behavior in the existing mapper pipeline without adding native-view state |
| 6 | try-fix | Let Windows native flyout behavior pull CollapseStyle directly from the virtual view via an internal interface and dual cache on behavior + collapse mode |
PASS | 6 files | Works, but materially broader than needed and introduces new cross-assembly coupling |
| 7 | try-fix | Register a native PaneDisplayModeProperty callback to re-enforce the requested collapse style whenever internal/native logic overwrites it |
PASS | 2 files | Passed after retries, but callback enforcement and weak-table bookkeeping are more invasive than necessary |
| 8 | try-fix | Register a shared MapPaneConfiguration mapper for both FlyoutLayoutBehavior and CollapseStyle and resolve the final native mode from combined state |
PASS | 2 files | Good unified-mapper variant, but less clearly aligned with the existing FlyoutBehavior update path than Candidate #5 |
| PR | PR #29927 | Add a property-changed callback and map CollapseStyle directly to WinUI PaneDisplayMode in the Windows mapper |
PASSED (Gate) | 4 files | Original PR |
Cross-Pollination
| Model | Round | New Ideas? | Details |
|---|---|---|---|
| claude-opus-4.6 | 2 | Yes | Make the existing Windows FlyoutBehavior mapping compute PaneDisplayMode from both current FlyoutBehavior and attached CollapseStyle. Tested as Candidate #5. |
| claude-sonnet-4.6 | 2 | Yes | Let native flyout behavior pull CollapseStyle from the virtual view as source-of-truth. Tested as Candidate #6. |
| gpt-5.3-codex | 2 | No | NO NEW IDEAS |
| gemini-3-pro-preview | 2 | No | NO NEW IDEAS |
| claude-opus-4.6 | 3 | No | NO NEW IDEAS |
| claude-sonnet-4.6 | 3 | No | NO NEW IDEAS |
| gpt-5.3-codex | 3 | No | NO NEW IDEAS |
| gemini-3-pro-preview | 3 | Yes | Re-enforce collapse style through a native PaneDisplayModeProperty callback. Tested as Candidate #7. |
| gpt-5.3-codex | 4 | Yes | Use one shared mapper entrypoint for pane configuration across FlyoutLayoutBehavior and CollapseStyle. Tested as Candidate #8. |
Exhausted: Yes
Selected Fix: Candidate #5 Simplest robust passing solution. It keeps collapse-style handling in the existing FlyoutBehavior mapper pipeline without introducing new native-view state, new interfaces, or callback enforcement.
📋 Report — Final Recommendation
Final Recommendation: REQUEST CHANGES
Final Recommendation: REQUEST CHANGES
Phase Status
| Phase | Status | Notes |
|---|---|---|
| Pre-Flight | COMPLETE | Windows FlyoutPage runtime CollapseStyle update issue with UI coverage in Issue18200 |
| Gate | PASSED | Windows full verification: test failed without fix and passed with fix |
| Try-Fix | COMPLETE | 8 attempts, 8 passing alternatives, Candidate #5 selected |
| Report | COMPLETE |
Summary
The PR fixes the reported Windows bug for the current UI test, so the submitted implementation is functionally valid. However, the try-fix phase found a better alternative: Candidate #5 keeps CollapseStyle handling inside the existing FlyoutBehavior mapping pipeline and achieves the same passing behavior with fewer moving parts and lower risk of future drift.
Root Cause
The Windows FlyoutPage stack already has a native FlyoutBehavior pipeline that determines PaneDisplayMode. The bug occurs because runtime CollapseStyle changes never trigger that pipeline, so Windows stays on the original pane mode. The PR addresses that by directly setting PaneDisplayMode from a separate mapper, but that approach bypasses the existing flow that also manages pane mode and can create a second source of truth.
Fix Quality
The PR's fix passes the new test, but it directly mutates native state from a dedicated CollapseStyle mapper instead of integrating with the existing FlyoutBehavior update path. Candidate #5 is stronger because it wraps the existing Windows FlyoutBehavior mapping with ModifyMapping, applies CollapseStyle after the base mapper runs, and reuses UpdateValue(nameof(IFlyoutView.FlyoutBehavior)) on property change. That keeps all pane-mode decisions in one mapper pipeline and avoids adding extra native-view state, interfaces, or callback enforcement.
📋 Expand PR Finalization Review
PR #29927 Finalization Review
Title & Description
Title: Needs improvement
- Current:
[Windows] Fix Flyout Page SetCollapseStyle doesn't have any change - Recommended:
[Windows] FlyoutPage: update CollapseStyle at runtime
Assessment: The current title captures the issue but reads awkwardly and does not clearly describe the implemented behavior. The recommended title is more searchable and matches the actual fix.
Description: Good enough, but could be stronger
What works:
- Includes the required NOTE block
- Clearly states the Windows-specific runtime-update problem
- Matches the main implementation at a high level
- Includes the linked issue and tested platform
Suggested improvements:
- Add the root cause:
CollapseStylechanged the attached property value, but the handler was never notified, soRootNavigationView.PaneDisplayModestayed stale. - Mention the actual implementation details: a property-changed callback was added on
CollapseStyleProperty, and a Windows mapper now translatesCollapseStyleto WinUIPaneDisplayMode. - Mention the added UI regression test for issue
#18200.
Code Review Findings
Important issue
CollapseStyle can be overwritten by later FlyoutBehavior updates
- Files:
src/Controls/src/Core/FlyoutPage/FlyoutPage.Mapper.cs:39-56,src/Controls/src/Core/FlyoutPage/FlyoutPage.cs:328-359,src/Core/src/Platform/Windows/MauiNavigationView.cs:173-204 - Problem:
MapCollapseStylesetsRootNavigationView.PaneDisplayModedirectly, but Windows FlyoutPage re-runsHandler.UpdateValue(nameof(FlyoutBehavior))on size and display-orientation changes. That flows intoUpdatePaneDisplayModeFromFlyoutBehavior(), which unconditionally resetsFlyoutBehavior.FlyouttoLeftMinimal, so a previously selectedCollapseStyle.Partialcan be lost after resize/orientation changes. - Why it matters: The PR fixes the immediate runtime toggle case, but the chosen pane mode is not sticky across later layout-driven updates.
- Recommendation: Integrate
CollapseStyleinto the WinUI pane-mode calculation path, or pin the pane display mode instead of setting it once ad hoc, so laterFlyoutBehaviorremaps do not undoCollapseStyle.Partial.
Suggestion
The UI test does not cover the reset path above
- Files:
src/Controls/tests/TestCases.HostApp/Issues/Issue18200.cs,src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18200.cs - Observation: The added test verifies toggling
CollapseStyleduring a steady-state session, but it does not exercise the size/orientation path that triggersFlyoutBehaviorremapping. - Recommendation: Extend the test coverage to validate that
CollapseStyle.Partialremains effective after a window resize or orientation/display-info change.
Overall
The PR metadata mostly matches the implementation, but I would update the title for clarity. More importantly, I would not consider the implementation fully finalized until the Windows pane-mode reset issue is addressed or explicitly ruled out.
kubaflo
left a comment
There was a problem hiding this comment.
Could you please review the AI's suggestions?
🤖 AI Summary📊 Expand Full Review —
|
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #29927 | Trigger handler updates when CollapseStyle changes, then map Windows CollapseStyle values to WinUI PaneDisplayMode at runtime |
PENDING (Gate) | src/Controls/src/Core/FlyoutPage/FlyoutPage.Mapper.cs, src/Controls/src/Core/PlatformConfiguration/WindowsSpecific/FlyoutPage.cs, src/Controls/tests/TestCases.HostApp/Issues/Issue18200.cs, src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18200.cs |
Original PR |
Issue: #18200 - Flyout Page SetCollapseStyle doesn't have any effect
PR: #29927 - [Windows] FlyoutPage: update CollapseStyle at runtime
Platforms Affected: Windows
Files Changed: 2 implementation, 2 test
Key Findings
- The linked issue reports that
WindowsSpecific.FlyoutPage.SetCollapseStyle(...)does not update FlyoutPage layout at runtime on Windows, even though the API previously worked in Xamarin.Forms. - The PR adds a property-changed callback to
CollapseStylePropertyand a Windows mapper that translatesCollapseStyleinto WinUINavigationViewPaneDisplayMode. - Test coverage was added as a HostApp issue page plus a shared Appium UI test, so the validation path is a Windows UI test using
Issue18200. - Prior discussion already raised two important concerns: later
FlyoutBehaviorremaps may overwrite the CollapseStyle-specific pane mode, and the new test only covers the immediate toggle path.
Edge Cases / Discussion Notes
- The issue thread includes a workaround that directly set WinUI
PaneDisplayModefrom a mapper, which is conceptually similar to the PR approach. - Inline review feedback questioned whether resize/orientation-driven
FlyoutBehaviorupdates can resetCollapseStyle.Partialafter the property changes. - The added UI test is Windows-only because
CollapseStyleis a Windows-specific API. - A prior PRAgent-style review exists on the PR thread, but this run is proceeding independently rather than resuming a partial local run.
File Classification
- Implementation:
src/Controls/src/Core/FlyoutPage/FlyoutPage.Mapper.cs - Implementation:
src/Controls/src/Core/PlatformConfiguration/WindowsSpecific/FlyoutPage.cs - Test (HostApp UI page):
src/Controls/tests/TestCases.HostApp/Issues/Issue18200.cs - Test (Shared UITest):
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18200.cs - Test type: UI test via HostApp + Appium shared test
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #29927 | Add a property-changed callback for CollapseStyle, then map the Windows collapse style to WinUI PaneDisplayMode at runtime |
PENDING (Gate) | src/Controls/src/Core/FlyoutPage/FlyoutPage.Mapper.cs, src/Controls/src/Core/PlatformConfiguration/WindowsSpecific/FlyoutPage.cs, src/Controls/tests/TestCases.HostApp/Issues/Issue18200.cs, src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18200.cs |
Original PR |
🚦 Gate — Test Verification
Result: PASSED
Gate Result: PASSED
Platform: windows
Mode: Full Verification
- Tests FAIL without fix:
- Tests PASS with fix:
Notes
- Verification used
Issue18200on Windows. - Without the fix, the UI test timed out waiting for the flyout item state change, reproducing the bug.
- With the fix applied, the same test passed, confirming the PR resolves the runtime collapse-style update issue.
Result: PASSED
Gate Result: PASSED
Platform: windows
Mode: Full Verification
- Tests FAIL without fix:
- Tests PASS with fix:
Notes
- Verification used
Issue18200on Windows. - Without the fix, the UI test timed out waiting for the expected element state change, reproducing the bug.
- With the fix applied, the same test passed, confirming the PR resolves the immediate runtime collapse-style update issue.
- Full verification report is available under
CustomAgentLogsTmp/PRState/29927/PRAgent/gate/verify-tests-fail/verification-report.md.
🔧 Fix — Analysis & Comparison
Result: PASSED
Gate Result: PASSED
Platform: windows
Mode: Full Verification
- Tests FAIL without fix:
- Tests PASS with fix:
Notes
- Verification used
Issue18200on Windows. - Without the fix, the UI test timed out waiting for the flyout item state change, reproducing the bug.
- With the fix applied, the same test passed, confirming the PR resolves the runtime collapse-style update issue.
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| 1 | try-fix | Integrate CollapseStyle into the existing flyout-behavior pane-mode pipeline via a generic override on MauiNavigationView, instead of a dedicated CollapseStyle mapper that writes PaneDisplayMode directly |
PASS | 3 files | Reuses the same update path that runs on size/orientation changes |
| 2 | try-fix | Make MapFlyoutLayoutBehavior the single authoritative Controls-layer place that applies both flyout behavior and collapse style, and re-trigger it when CollapseStyle changes |
PASS | 2 files | Keeps all changes in Controls and reapplies after orientation-triggered behavior remaps |
| 3 | try-fix | Append collapse-style handling onto the existing IFlyoutView.FlyoutBehavior mapping path, and re-trigger that path when CollapseStyle changes |
PASS | 2 files | Most directly aligns with the existing pane-mode update path |
| 4 | try-fix | Modify mapping to run default flyout-behavior logic then apply a direct collapse-style override | FAIL | 1 file | Did not reliably hide the flyout item in the test environment |
| 5 | try-fix | Reset cached flyout-behavior tracking in MauiNavigationView, then re-run flyout-behavior mapping from a clean base before applying CollapseStyle |
PASS | 3 files | Explicit cache invalidation makes UpdateValue(FlyoutBehavior) effective again |
| 6 | try-fix | Move both flyout behavior and collapse-style state into native MauiNavigationView dependency properties so one native method computes the final PaneDisplayMode |
PASS | 4 files | Robust single-source-of-truth design, but broader than necessary |
| PR | PR #29927 | Add a property-changed callback for CollapseStyle, then map the Windows collapse style to WinUI PaneDisplayMode at runtime |
PASSED (Gate) | 4 files | Original PR |
Cross-Pollination
| Model | Round | New Ideas? | Details |
|---|---|---|---|
| claude-opus-4.6 | 1 | Yes | Candidate #1: move CollapseStyle through the flyout-behavior pipeline with a MauiNavigationView override instead of a side-channel mapper. |
| claude-sonnet-4.6 | 1 | Yes | Candidate #2: keep pane-mode logic entirely in MapFlyoutLayoutBehavior and re-run that mapping when CollapseStyle changes. |
| gpt-5.3-codex | 1 | Yes | Candidate #3: compose collapse-style handling onto the existing IFlyoutView.FlyoutBehavior mapping and re-trigger that mapping on property change. |
| gemini-3-pro-preview | 1 | Yes | Candidate #4: rerun the default flyout-behavior mapping and then apply a direct override. |
| claude-opus-4.6 | 2 | No | NO NEW IDEAS |
| claude-sonnet-4.6 | 2 | Yes | Candidate #5: reset cached flyout-behavior tracking before re-running flyout-behavior mapping from a clean base. |
| gpt-5.3-codex | 2 | No | NO NEW IDEAS |
| gemini-3-pro-preview | 2 | Yes | Candidate #6: use native state/binding-style aggregation in MauiNavigationView so one method computes the final pane mode. |
| claude-opus-4.6 | 3 | No | NO NEW IDEAS |
| claude-sonnet-4.6 | 3 | No | NO NEW IDEAS |
| gpt-5.3-codex | 3 | No | NO NEW IDEAS |
| gemini-3-pro-preview | 3 | No | NO NEW IDEAS |
Exhausted: Yes
Selected Fix: Candidate #3 Simplest robust passing solution. It keeps CollapseStyle in the same IFlyoutView.FlyoutBehavior mapping path that already owns pane-mode updates, so later size/orientation remaps naturally preserve the requested collapse style without adding extra native state or broader plumbing.
📋 Report — Final Recommendation
Result: PASSED
Gate Result: PASSED
Platform: windows
Mode: Full Verification
- Tests FAIL without fix:
- Tests PASS with fix:
Notes
- Verification used
Issue18200on Windows. - Without the fix, the UI test timed out waiting for the flyout item state change, reproducing the bug.
- With the fix applied, the same test passed, confirming the PR resolves the runtime collapse-style update issue.
Final Recommendation: REQUEST CHANGES
Final Recommendation: REQUEST CHANGES
Phase Status
| Phase | Status | Notes |
|---|---|---|
| Pre-Flight | COMPLETE | Windows FlyoutPage runtime CollapseStyle update issue with UI coverage in Issue18200 |
| Gate | PASSED | Windows full verification: test failed without fix and passed with fix |
| Try-Fix | COMPLETE | 6 attempts tested, 5 passing alternatives plus the PR fix; Candidate #3 selected |
| Report | COMPLETE |
Summary
The PR's current implementation fixes the immediate Issue18200 runtime toggle scenario on Windows, and the new UI test correctly proves that. However, the try-fix phase found multiple simpler or better-aligned passing alternatives. The strongest option was Candidate #3, which keeps CollapseStyle in the same IFlyoutView.FlyoutBehavior mapping path that already governs pane-mode updates, instead of introducing a separate CollapseStyle mapper that writes native PaneDisplayMode directly.
Root Cause
Windows FlyoutPage already has an existing pipeline that recalculates PaneDisplayMode from FlyoutBehavior, including later re-evaluations caused by size or orientation changes. The bug exists because runtime CollapseStyle changes were not routed through that pipeline, so the requested compact/minimal state never got reflected. PR #29927 fixes the immediate symptom by adding a property-changed callback and directly mutating RootNavigationView.PaneDisplayMode, but that creates a second pane-mode decision path separate from the existing flyout-behavior flow.
Fix Quality
The submitted fix is functionally valid for the added regression test, but it bypasses the existing pane-mode update path and therefore is not the cleanest implementation. Candidate #3 achieved the same passing behavior with only two changed files by composing CollapseStyle into the existing IFlyoutView.FlyoutBehavior mapper path and re-triggering that path when the attached property changes. That keeps one authoritative pipeline for pane-mode decisions, aligns better with existing Windows FlyoutPage behavior, and avoids adding extra native state or a side-channel mapper.
📋 Expand PR Finalization Review
PR #29927 Finalization Review
Title & Description
Title: Needs improvement
- Current:
[Windows] Fix Flyout Page SetCollapseStyle doesn't have any change - Recommended:
[Windows] FlyoutPage: update CollapseStyle at runtime
Assessment: The current title captures the issue but reads awkwardly and does not clearly describe the implemented behavior. The recommended title is more searchable and matches the actual fix.
Description: Good enough, but could be stronger
What works:
- Includes the required NOTE block
- Clearly states the Windows-specific runtime-update problem
- Matches the main implementation at a high level
- Includes the linked issue and tested platform
Suggested improvements:
- Add the root cause:
CollapseStylechanged the attached property value, but the handler was never notified, soRootNavigationView.PaneDisplayModestayed stale. - Mention the actual implementation details: a property-changed callback was added on
CollapseStyleProperty, and a Windows mapper now translatesCollapseStyleto WinUIPaneDisplayMode. - Mention the added UI regression test for issue
#18200.
Code Review Findings
Important issue
CollapseStyle can be overwritten by later FlyoutBehavior updates
- Files:
src/Controls/src/Core/FlyoutPage/FlyoutPage.Mapper.cs:39-56,src/Controls/src/Core/FlyoutPage/FlyoutPage.cs:328-359,src/Core/src/Platform/Windows/MauiNavigationView.cs:173-204 - Problem:
MapCollapseStylesetsRootNavigationView.PaneDisplayModedirectly, but Windows FlyoutPage re-runsHandler.UpdateValue(nameof(FlyoutBehavior))on size and display-orientation changes. That flows intoUpdatePaneDisplayModeFromFlyoutBehavior(), which unconditionally resetsFlyoutBehavior.FlyouttoLeftMinimal, so a previously selectedCollapseStyle.Partialcan be lost after resize/orientation changes. - Why it matters: The PR fixes the immediate runtime toggle case, but the chosen pane mode is not sticky across later layout-driven updates.
- Recommendation: Integrate
CollapseStyleinto the WinUI pane-mode calculation path, or pin the pane display mode instead of setting it once ad hoc, so laterFlyoutBehaviorremaps do not undoCollapseStyle.Partial.
Suggestion
The UI test does not cover the reset path above
- Files:
src/Controls/tests/TestCases.HostApp/Issues/Issue18200.cs,src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18200.cs - Observation: The added test verifies toggling
CollapseStyleduring a steady-state session, but it does not exercise the size/orientation path that triggersFlyoutBehaviorremapping. - Recommendation: Extend the test coverage to validate that
CollapseStyle.Partialremains effective after a window resize or orientation/display-info change.
Overall
The PR metadata mostly matches the implementation, but I would update the title for clarity. More importantly, I would not consider the implementation fully finalized until the Windows pane-mode reset issue is addressed or explicitly ruled out.
#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>
@kubaflo , I have addressed the AI suggestion. |
🚦 Gate - Test Before and After Fix📊 Expand Full Gate —
|
| Test | Without Fix (expect FAIL) | With Fix (expect PASS) |
|---|---|---|
🖥️ Issue18200 Issue18200 |
✅ FAIL — 568s | ✅ PASS — 464s |
🔴 Without fix — 🖥️ Issue18200: FAIL ✅ · 568s
Determining projects to restore...
Restored D:\a\1\s\src\Graphics\src\Graphics.Win2D\Graphics.Win2D.csproj (in 21.93 sec).
Restored D:\a\1\s\src\Graphics\src\Graphics\Graphics.csproj (in 21.93 sec).
Restored D:\a\1\s\src\Essentials\src\Essentials.csproj (in 8.49 sec).
Restored D:\a\1\s\src\Core\src\Core.csproj (in 16.79 sec).
Restored D:\a\1\s\src\Controls\tests\TestCases.HostApp\Controls.TestCases.HostApp.csproj (in 5.74 sec).
Restored D:\a\1\s\src\Controls\src\Xaml\Controls.Xaml.csproj (in 30 ms).
Restored D:\a\1\s\src\Controls\src\Core\Controls.Core.csproj (in 31 ms).
Restored D:\a\1\s\src\Core\maps\src\Maps.csproj (in 14.52 sec).
Restored D:\a\1\s\src\Controls\Maps\src\Controls.Maps.csproj (in 35 ms).
Restored D:\a\1\s\src\Controls\Foldable\src\Controls.Foldable.csproj (in 17 ms).
Restored D:\a\1\s\src\BlazorWebView\src\Maui\Microsoft.AspNetCore.Components.WebView.Maui.csproj (in 23 ms).
3 of 14 projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684000
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.13684000
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684000
Graphics.Win2D -> D:\a\1\s\artifacts\bin\Graphics.Win2D\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Graphics.Win2D.WinUI.Desktop.dll
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.13684000
Core -> D:\a\1\s\artifacts\bin\Core\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684000
Maps -> D:\a\1\s\artifacts\bin\Maps\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Maps.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.13684000
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.13684000
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684000
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
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684000
Controls.Maps -> D:\a\1\s\artifacts\bin\Controls.Maps\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.Maps.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684000
Controls.Xaml -> D:\a\1\s\artifacts\bin\Controls.Xaml\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.Xaml.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:47.01
Determining projects to restore...
Restored D:\a\1\s\src\Controls\tests\CustomAttributes\Controls.CustomAttributes.csproj (in 851 ms).
Restored D:\a\1\s\src\TestUtils\src\VisualTestUtils\VisualTestUtils.csproj (in 3 ms).
Restored D:\a\1\s\src\TestUtils\src\VisualTestUtils.MagickNet\VisualTestUtils.MagickNet.csproj (in 6.83 sec).
Restored D:\a\1\s\src\Controls\tests\TestCases.WinUI.Tests\Controls.TestCases.WinUI.Tests.csproj (in 8.98 sec).
Restored D:\a\1\s\src\TestUtils\src\UITest.Core\UITest.Core.csproj (in 1 ms).
Restored D:\a\1\s\src\TestUtils\src\UITest.Appium\UITest.Appium.csproj (in 2 ms).
Restored D:\a\1\s\src\TestUtils\src\UITest.NUnit\UITest.NUnit.csproj (in 1.62 sec).
Restored D:\a\1\s\src\TestUtils\src\UITest.Analyzers\UITest.Analyzers.csproj (in 5.55 sec).
7 of 15 projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684000
Graphics -> D:\a\1\s\artifacts\bin\Graphics\Debug\net10.0\Microsoft.Maui.Graphics.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.13684000
Essentials -> D:\a\1\s\artifacts\bin\Essentials\Debug\net10.0\Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684000
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.13684000
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
VisualTestUtils -> D:\a\1\s\artifacts\bin\VisualTestUtils\Debug\netstandard2.0\VisualTestUtils.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.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:01 PM FixtureSetup for Issue18200(Windows)
>>>>> 3/29/2026 7:35:09 PM VerifyFlyoutCollapseStyleBehaviorChanges Start
>>>>> 3/29/2026 7:35:29 PM VerifyFlyoutCollapseStyleBehaviorChanges Stop
>>>>> 3/29/2026 7:35:29 PM Log types:
Failed VerifyFlyoutCollapseStyleBehaviorChanges [20 s]
Error Message:
System.TimeoutException : Timed out waiting for element...
Stack Trace:
at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2757
at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2784
at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 793
at Microsoft.Maui.TestCases.Tests.Issues.Issue18200.VerifyFlyoutCollapseStyleBehaviorChanges() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18200.cs:line 26
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.10] 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: 48.9120 Seconds
🟢 With fix — 🖥️ Issue18200: PASS ✅ · 464s
Determining projects to restore...
All projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684000
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.13684000
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684000
Graphics.Win2D -> D:\a\1\s\artifacts\bin\Graphics.Win2D\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Graphics.Win2D.WinUI.Desktop.dll
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.13684000
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.13684000
Maps -> D:\a\1\s\artifacts\bin\Maps\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Maps.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684000
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.13684000
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684000
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684000
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684000
Controls.Maps -> D:\a\1\s\artifacts\bin\Controls.Maps\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.Maps.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.Xaml -> D:\a\1\s\artifacts\bin\Controls.Xaml\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.Xaml.dll
Controls.Foldable -> D:\a\1\s\artifacts\bin\Controls.Foldable\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.Foldable.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:32.51
Determining projects to restore...
All projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684000
Graphics -> D:\a\1\s\artifacts\bin\Graphics\Debug\net10.0\Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684000
Essentials -> D:\a\1\s\artifacts\bin\Essentials\Debug\net10.0\Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13684000
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.13684000
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.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.Appium -> D:\a\1\s\artifacts\bin\UITest.Appium\Debug\net10.0\UITest.Appium.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:02 PM FixtureSetup for Issue18200(Windows)
>>>>> 3/29/2026 7:43:10 PM VerifyFlyoutCollapseStyleBehaviorChanges Start
>>>>> 3/29/2026 7:43:14 PM VerifyFlyoutCollapseStyleBehaviorChanges Stop
Passed VerifyFlyoutCollapseStyleBehaviorChanges [4 s]
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.10] Discovering: Controls.TestCases.WinUI.Tests
[xUnit.net 00:00:00.36] Discovered: Controls.TestCases.WinUI.Tests
Test Run Successful.
Total tests: 1
Passed: 1
Total time: 27.5190 Seconds
📁 Fix files reverted (4 files)
eng/pipelines/ci-copilot.ymlsrc/Controls/src/Core/FlyoutPage/FlyoutPage.Mapper.cssrc/Controls/src/Core/PlatformConfiguration/WindowsSpecific/FlyoutPage.cssrc/Core/src/Platform/Windows/MauiNavigationView.cs
🤖 AI Summary📊 Expand Full Review —
|
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #29927 | Add propertyChanged callback + FlyoutPaneDisplayMode property + mapper registration |
✅ PASSED (Gate) | WindowsSpecific/FlyoutPage.cs, FlyoutPage.Mapper.cs, MauiNavigationView.cs |
Original PR |
🔧 Fix — Analysis & Comparison
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| 1 | try-fix (claude-opus-4.6) | propertyChanged calls handler.UpdateValue("FlyoutBehavior"); replaced FlyoutBehavior mapper on Windows to apply CollapseStyle override after base call | PASS | 2 files (WindowsSpecific/FlyoutPage.cs, FlyoutPage.Mapper.cs) | Simpler no new state on MauiNavigationView |
| 2 | try-fix (claude-sonnet-4.6) | propertyChanged directly calls | |||
| avView.UpdateFlyoutPaneDisplayMode(mode); added method + property to MauiNavigationView | PASS | 2 files (WindowsSpecific/FlyoutPage.cs, MauiNavigationView.cs) | No mapper changes needed | ||
| 3 | try-fix (gpt-5.3-codex) | Hooked FlyoutPage.PropertyChanged (not CollapseStyleProperty metadata) to trigger UpdateValue(FlyoutBehavior) | FAIL | 1 file (FlyoutPage.cs) | Attached property changes not surfaced through PropertyChanged override |
| 4 | try-fix (gpt-5.4) | propertyChanged calls handler.UpdateValue(FlyoutLayoutBehavior); modified MapFlyoutLayoutBehavior on Windows to also apply CollapseStyle override | PASS | 3 files | Bundles CollapseStyle into FlyoutLayoutBehavior mapper path |
| PR | PR #29927 | propertyChanged -> handler.UpdateValue(nameof(CollapseStyleProperty)) -> new MapCollapseStyle mapper sets FlyoutPaneDisplayMode + PaneDisplayMode; property on MauiNavigationView ensures robustness through re-evaluations | PASSED (Gate) | 3 files | Dedicated mapper; minor code quality issues |
Cross-Pollination
| Model | Round | New Ideas? | Details |
|---|---|---|---|
| claude-opus-4.6 | 2 | No | All approaches are detect-change + update-PaneDisplayMode. Space exhausted. |
Exhausted: Yes
Selected Fix: PR #29927 Dedicated mapper approach is architecturally cleanest, consistent with iOS platform-specific pattern. FlyoutPaneDisplayMode property ensures robustness. Gate PASSED. Minor code quality issues to address.
📋 Report — Final Recommendation
✅ Final Recommendation: APPROVE
Phase Status
| Phase | Status | Notes |
|---|---|---|
| Pre-Flight | ✅ COMPLETE | Issue #18200, Windows-only, 3 impl + 2 test files |
| Gate | ✅ PASSED | Windows platform |
| Try-Fix | ✅ COMPLETE | 4 attempts: 3 passing, 1 failing; cross-pollination exhausted |
| Report | ✅ COMPLETE |
Summary
PR #29927 fixes a long-standing issue where FlyoutPage.SetCollapseStyle() on Windows had no runtime effect. The fix is correct, well-structured, and the gate test passes. Three independent alternative approaches were found during Try-Fix, confirming the fix space is well-understood. The PR's chosen architecture is the most maintainable. Minor code quality issues should be addressed before merge.
Root Cause
CollapseStyleProperty in WindowsSpecific/FlyoutPage.cs was declared without a propertyChanged callback. As an attached BindableProperty, runtime value changes generated no notifications — neither the handler nor the platform view was ever told to update. The UpdatePaneDisplayModeFromFlyoutBehavior path in MauiNavigationView always defaulted to LeftMinimal, ignoring any previously-set CollapseStyle.
Fix Quality
The PR's three-part fix is architecturally sound:
-
propertyChangedcallback onCollapseStyleProperty— minimal, correct hook; callshandler.UpdateValue(nameof(CollapseStyleProperty))to route through the mapper system (consistent with how iOS platform-specific properties work in the same file). -
MapCollapseStylemapper registered inFlyoutPage.Mapper.cs— dedicated mapper for CollapseStyle (clean separation of concerns, consistent with iOSMapPrefersHomeIndicatorAutoHiddenPropertypattern). SetsFlyoutPaneDisplayModeonRootNavigationViewto persist the desired mode. -
FlyoutPaneDisplayModeproperty onMauiNavigationView— ensures CollapseStyle survives layout-drivenFlyoutBehaviorre-evaluations (e.g., resize/orientation).UpdatePaneDisplayModeFromFlyoutBehaviornow reads this property so CollapseStyle.Partial (LeftCompact) persists even when FlyoutBehavior is re-mapped.
Simpler alternatives existed (Try-Fix Attempt 1: 2 files, no new state) but the PR's approach is more correct: dedicated mapper for each concern, FlyoutPaneDisplayMode stored explicitly on the platform view.
Issues to Address Before Merge
These should be fixed but do not require a different fix approach:
-
PlatformAffected.UWP→PlatformAffected.WindowsinIssue18200.csline 6 — UWP is the wrong enum value for WinUI3/MAUI Windows apps. -
Extra space in
usingstatement inIssue18200.csline 2:using Microsoft.Maui.Controls.PlatformConfiguration.WindowsSpecific;has a double space. -
Mixed indentation in
Issue18200.cs— file uses spaces in some places, tabs in others. Rundotnet formatto normalize. -
Test validation strength — the test verifies flyout item visibility (Partial = visible strip, Full = hidden) which is a valid proxy for pane display mode. Acceptable given the Windows NavigationView behavior.
> [!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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue details FlyoutPage on Windows did not update its layout when the CollapseStyle property changed at runtime. ### Description of Change <!-- Enter description of the fix in this section --> This update enables dynamic support for the CollapseStyle property in FlyoutPage on Windows. It allows the flyout pane to update at runtime when the property changes, ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #18200 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Windows | Before | After | |---------|--------| | **Windows**<br> <video src="https://github.com/user-attachments/assets/9d7844d7-af65-465a-abb3-b611290afe1f" width="400" height="250"> |**Windows**<br> <video src="https://github.com/user-attachments/assets/2edd0934-c369-4dda-8269-e22291769c2e" width="400" height="250"> |
> [!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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue details FlyoutPage on Windows did not update its layout when the CollapseStyle property changed at runtime. ### Description of Change <!-- Enter description of the fix in this section --> This update enables dynamic support for the CollapseStyle property in FlyoutPage on Windows. It allows the flyout pane to update at runtime when the property changes, ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes dotnet#18200 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Windows | Before | After | |---------|--------| | **Windows**<br> <video src="https://github.com/user-attachments/assets/9d7844d7-af65-465a-abb3-b611290afe1f" width="400" height="250"> |**Windows**<br> <video src="https://github.com/user-attachments/assets/2edd0934-c369-4dda-8269-e22291769c2e" width="400" height="250"> |
Note
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!
Issue details
FlyoutPage on Windows did not update its layout when the CollapseStyle property changed at runtime.
Description of Change
This update enables dynamic support for the CollapseStyle property in FlyoutPage on Windows. It allows the flyout pane to update at runtime when the property changes,
Issues Fixed
Fixes #18200
Tested the behavior in the following platforms.
Without-Fix.mp4
With-Fix.mp4