[Windows] Fix for Shell.FlyoutBehavior="Flyout" forces the title height space above the tab bar even if the page title is empty#30382
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR fixes an issue on Windows where Shell.FlyoutBehavior="Flyout" would always reserve header space above the tab bar even when the page title is empty. It adds logic to detect empty headers and collapse them, and ensures this logic runs on toolbar updates and tab navigation. A new UI test for the empty-title scenario is also included.
- Introduces
UpdateHeaderVisibility,IsHeaderContentEmpty, andCollapseEmptyHeaderinRootNavigationViewto hide empty headers. - Hooks
UpdateHeaderVisibilityinto toolbar changes and tab selection inShellView. - Adds a UITest (
Issue30254) and corresponding HostApp page to cover the empty-title behavior.
Reviewed Changes
Copilot reviewed 4 out of 6 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/Core/src/Platform/Windows/RootNavigationView.cs | Adds header-visibility methods and calls on toolbar change |
| src/Controls/src/Core/Handlers/Shell/Windows/ShellView.cs | Calls header-visibility update after tab selection |
| src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue30254.cs | Adds shared UITest for empty-title header hiding |
| src/Controls/tests/TestCases.HostApp/Issues/Issue30254.cs | Adds HostApp Shell page with empty and non-empty title cases |
Comments suppressed due to low confidence (2)
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue30254.cs:19
- The test covers the empty-title scenario but does not verify that the header reappears when navigating to a page with a non-empty title. Consider adding steps (e.g., tapping the second tab) and assertions to confirm the header is shown for the "With Title" case.
App.WaitForElement("MainPageButton");
src/Controls/src/Core/Handlers/Shell/Windows/ShellView.cs:279
- The method
UpdateHeaderVisibility()is not defined inShellView. You need to call the new method on theRootNavigationViewinstance (for example,sender.UpdateHeaderVisibility()or using a stored reference to the navigation view), otherwise this will not compile or have no effect.
UpdateHeaderVisibility();
|
/azp run MAUI-UITests-public |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
|
||
| [Test] | ||
| [Category(UITestCategories.Shell)] | ||
| public void ShouldHideHeaderWhenTitleEmpty() |
There was a problem hiding this comment.
Pending snapshots on Mac and Windows.
Already available in the latest build.
There was a problem hiding this comment.
@jsuarezruiz, I have successfully added snapshots for Mac and Windows.
|
Oh waw, thanks so much for sharing a solution to this issue, that was surprisingly fast! Hopefully the code has no issues and the pull request will be accepted :) |
|
/rebase |
3cbc85b to
3fb9893
Compare
d454721 to
fa7e783
Compare
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 30382Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 30382" |
|
Coming back to this after 6 months, hopefully there can be progress and attention on this issue, as iterating frontend design is much faster on Windows (due to build times), and having to account for the space offset when designing a page is not very intuitive. |
|
/rebase |
be0a988 to
d87d994
Compare
|
Noooo the azure unit tests failed! |
🤖 AI Summary📊 Expand Full Review —
|
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #30382 | Collapse header via Header = null + InvalidateMeasure() when title/content empty in LeftMinimal mode |
✅ PASSED (Gate) | RootNavigationView.cs, ShellView.cs |
Uses FindName for template part detection |
🔧 Fix — Analysis & Comparison
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| 1 | try-fix (claude-opus-4.6) | Toolbar Self-Managed Visibility — MauiToolbar updates its own Visibility; RootNavigationView reacts via callback |
✅ PASS | MauiToolbar.xaml.cs, RootNavigationView.cs |
No ShellView.cs changes needed; encapsulates in MauiToolbar |
| 2 | try-fix (claude-sonnet-4.6) | Inline check in UpdateToolbarPlacement() — conditional Header = HasNoToolbarContent() ? null : Toolbar; ShellView calls UpdateToolbarPlacement() on tab switch |
✅ PASS | RootNavigationView.cs, ShellView.cs |
Same 2 files as PR but different structure; no separate methods |
| 3 | try-fix (gpt-5.3-codex) | Collapse HeaderContent template part visibility directly when header is empty in LeftMinimal |
✅ PASS | RootNavigationView.cs, ShellView.cs |
Manipulates HeaderContent visibility instead of nulling Header |
| 4 | try-fix (gpt-5.4) | Reactive subscription in MauiNavigationView/MauiToolbar — auto-recomputes Header on PropertyChanged for Title/TitleView |
✅ PASS | MauiNavigationView.cs, MauiToolbar.xaml.cs, RootNavigationView.cs |
Most automatic; handles dynamic title changes; most complex |
| 5 | try-fix (claude-sonnet-4.6) | AlwaysShowHeader = false + conditional Header = null — WinUI native collapse, no InvalidateMeasure() needed |
✅ PASS | RootNavigationView.cs, ShellView.cs |
Most idiomatic WinUI approach; simplest fix |
| PR | PR #30382 | UpdateHeaderVisibility() with Header = null + InvalidateMeasure(); IsHeaderContentEmpty() uses FindName template detection |
✅ PASSED (Gate) | RootNavigationView.cs, ShellView.cs |
Uses FindName string lookups; adds tab-change hook |
Cross-Pollination
| Model | Round | New Ideas? | Details |
|---|---|---|---|
| claude-sonnet-4.6 | 1 | Yes | AlwaysShowHeader = false → became Attempt 5 |
| claude-opus-4.6 | 2 | No | NO NEW IDEAS — solution space exhausted |
Exhausted: Yes
Selected Fix: Attempt 5 (AlwaysShowHeader = false) — most idiomatic WinUI approach; leverages built-in NavigationView behavior; eliminates InvalidateMeasure() requirement; comparable simplicity to PR but more correct. PR's FindName approach is fragile and relies on implementation details of the WinUI template.
📋 Report — Final Recommendation
⚠️ Final Recommendation: REQUEST CHANGES
Phase Status
| Phase | Status | Notes |
|---|---|---|
| Pre-Flight | ✅ COMPLETE | Issue #30254, Windows Shell flyout header space |
| Gate | ✅ PASSED | windows |
| Try-Fix | ✅ COMPLETE | 5 attempts, all 5 passing; solution space exhausted |
| Report | ✅ COMPLETE |
Summary
PR #30382 fixes a real, verified bug: Windows Shell with FlyoutBehavior="Flyout" reserves header space above the tab bar even when the page title is empty. The fix is functionally correct and passes the gate. However, exploration identified a more idiomatic approach, and the PR code has quality concerns that should be addressed before merge.
Selected Fix: Attempt 5 (AlwaysShowHeader = false) is recommended over the PR's current approach — it leverages a built-in WinUI NavigationView property, eliminating the manual InvalidateMeasure() call and making the fix more robust.
Root Cause
In RootNavigationView, UpdateToolbarPlacement() always assigns Header = Toolbar in LeftMinimal pane mode (Flyout behavior), even when the Toolbar has no visible content. WinUI's NavigationView defaults to AlwaysShowHeader = true, meaning the header row always reserves space even when the content renders invisibly — producing the unwanted gap above the tab bar.
Fix Quality
Issues with the PR's current implementation:
-
AlwaysShowHeader = falsenot used — requires unnecessaryInvalidateMeasure()
WinUI's built-inAlwaysShowHeaderproperty, when set tofalse, natively collapses the header area whenHeader = nullwithout needingInvalidateMeasure(). The PR uses the defaulttrueand compensates with an explicitInvalidateMeasure()call. Attempt 5 confirmed thatAlwaysShowHeader = false+Header = nullworks cleanly without it.Suggested fix: Add
AlwaysShowHeader = false;toRootNavigationView's constructor and remove theInvalidateMeasure()call fromCollapseEmptyHeader(). -
Fragile
FindNamestring-based template lookups
HasMenuBarItems()usesFindName("menuContent")andHasTitleIcon()usesFindName("titleIcon"). These rely on internal template part names that could change across WinUI versions and are not part of the public contract.Suggested fix: Access toolbar content through typed properties or the existing
MauiToolbarAPI rather thanFindName. -
PaneDisplayModeChangeddoes not callUpdateHeaderVisibility()
WhenFlyoutBehaviorchanges at runtime (which triggers aPaneDisplayModechange),UpdateHeaderVisibility()is never called. The header state could be stale after a runtime FlyoutBehavior change.Suggested fix: Call
UpdateHeaderVisibility()at the end ofRootNavigationView.PaneDisplayModeChanged. -
Trailing whitespace in
RootNavigationView.cs
The diff shows trailing whitespace on several lines (e.g., afterreturn;on line 261, afterCollapseEmptyHeader();on line 266, afterHasTitleIcon();on line 281). This will faildotnet formatchecks. -
Test only validates initial state; no tab-switch coverage
ShouldHideHeaderWhenTitleEmpty()waits forMainPageButtonand immediately takes a screenshot — it only verifies the empty-title page on initial load. The core behavior being fixed (switching between tabs with and without titles) is not tested.Suggested fix: Add a second test step that taps to the "With Title" tab, verifies the header appears, then switches back and verifies the header disappears.
-
5 existing test snapshots resaved without per-test explanation
ShellFlowDirectionUpdate,VerifyFlyoutBackgroundColor,VerifyHamburgerIcon,Issue23834FlyoutMisbehavior,VerifyFlyoutContentHasNoDefaultCornerRadiuswere all resaved. The PR explanation ("ContentPage did not have a title") is plausible but should be verified — any snapshot change for a test not directly related to this issue risks hiding regressions.
Suggested Alternative
Add AlwaysShowHeader = false; to RootNavigationView's constructor, remove InvalidateMeasure() from CollapseEmptyHeader(), add the UpdateHeaderVisibility() call in PaneDisplayModeChanged, fix trailing whitespace, and strengthen the test to verify tab-switching behavior.
kubaflo
left a comment
There was a problem hiding this comment.
Could you please review the AI's summary?
@kubaflo, The agent review for this PR appears to be in an incomplete state. Please find the AI summary for your reference. AI summary comment: #30382 (comment) |
🚦 Gate - Test Before and After Fix📊 Expand Full Gate —
|
| Test | Without Fix (expect FAIL) | With Fix (expect PASS) |
|---|---|---|
🖥️ Issue30254 Issue30254 |
✅ FAIL — 574s | ✅ PASS — 456s |
🔴 Without fix — 🖥️ Issue30254: FAIL ✅ · 574s
Determining projects to restore...
Restored D:\a\1\s\src\Graphics\src\Graphics.Win2D\Graphics.Win2D.csproj (in 29.49 sec).
Restored D:\a\1\s\src\Graphics\src\Graphics\Graphics.csproj (in 29.46 sec).
Restored D:\a\1\s\src\Essentials\src\Essentials.csproj (in 10.12 sec).
Restored D:\a\1\s\src\Core\src\Core.csproj (in 15.68 sec).
Restored D:\a\1\s\src\Core\maps\src\Maps.csproj (in 14.22 sec).
Restored D:\a\1\s\src\Controls\tests\TestCases.HostApp\Controls.TestCases.HostApp.csproj (in 8.71 sec).
Restored D:\a\1\s\src\Controls\src\Core\Controls.Core.csproj (in 18 ms).
Restored D:\a\1\s\src\Controls\src\Xaml\Controls.Xaml.csproj (in 42 ms).
Restored D:\a\1\s\src\Controls\Foldable\src\Controls.Foldable.csproj (in 17 ms).
Restored D:\a\1\s\src\Controls\Maps\src\Controls.Maps.csproj (in 21 ms).
Restored D:\a\1\s\src\BlazorWebView\src\Maui\Microsoft.AspNetCore.Components.WebView.Maui.csproj (in 26 ms).
3 of 14 projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13730064
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.13730064
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.13730064
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.13730064
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.13730064
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13730064
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.13730064
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13730064
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13730064
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13730064
Controls.Maps -> D:\a\1\s\artifacts\bin\Controls.Maps\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.Maps.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
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:52.18
Determining projects to restore...
Restored D:\a\1\s\src\TestUtils\src\VisualTestUtils\VisualTestUtils.csproj (in 717 ms).
Restored D:\a\1\s\src\TestUtils\src\UITest.NUnit\UITest.NUnit.csproj (in 1.27 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.1 sec).
Restored D:\a\1\s\src\TestUtils\src\UITest.Analyzers\UITest.Analyzers.csproj (in 4.82 sec).
Restored D:\a\1\s\src\TestUtils\src\VisualTestUtils.MagickNet\VisualTestUtils.MagickNet.csproj (in 17.45 sec).
Restored D:\a\1\s\src\Controls\tests\CustomAttributes\Controls.CustomAttributes.csproj (in 6 ms).
Restored D:\a\1\s\src\Controls\tests\TestCases.WinUI.Tests\Controls.TestCases.WinUI.Tests.csproj (in 9.48 sec).
7 of 15 projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13730064
Graphics -> D:\a\1\s\artifacts\bin\Graphics\Debug\net10.0\Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13730064
Essentials -> D:\a\1\s\artifacts\bin\Essentials\Debug\net10.0\Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13730064
Controls.CustomAttributes -> D:\a\1\s\artifacts\bin\Controls.CustomAttributes\Debug\net10.0\Controls.CustomAttributes.dll
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.13730064
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
>>>>> 4/2/2026 10:44:37 PM FixtureSetup for Issue30254(Windows)
>>>>> 4/2/2026 10:44:51 PM ShouldHideHeaderWhenTitleEmpty Start
>>>>> 4/2/2026 10:44:53 PM ShouldHideHeaderWhenTitleEmpty Stop
>>>>> 4/2/2026 10:44:53 PM Log types:
Failed ShouldHideHeaderWhenTitleEmpty [3 s]
Error Message:
VisualTestUtils.VisualTestFailedException :
Snapshot different than baseline: ShouldHideHeaderWhenTitleEmpty.png (2.22% 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.Issue30254.ShouldHideHeaderWhenTitleEmpty() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue30254.cs:line 20
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.11] Discovering: Controls.TestCases.WinUI.Tests
[xUnit.net 00:00:00.35] Discovered: Controls.TestCases.WinUI.Tests
Total tests: 1
Failed: 1
Test Run Failed.
Total time: 36.7622 Seconds
🟢 With fix — 🖥️ Issue30254: PASS ✅ · 456s
Determining projects to restore...
All projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13730064
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.13730064
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.13730064
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.13730064
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.13730064
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.13730064
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.13730064
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13730064
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.13730064
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.13730064
Controls.Foldable -> D:\a\1\s\artifacts\bin\Controls.Foldable\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.Foldable.dll
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.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:36.20
Determining projects to restore...
All projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13730064
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.13730064
Essentials -> D:\a\1\s\artifacts\bin\Essentials\Debug\net10.0\Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13730064
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.13730064
Controls.Core -> D:\a\1\s\artifacts\bin\Controls.Core\Debug\net10.0\Microsoft.Maui.Controls.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.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
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
>>>>> 4/2/2026 10:52:18 PM FixtureSetup for Issue30254(Windows)
>>>>> 4/2/2026 10:52:29 PM ShouldHideHeaderWhenTitleEmpty Start
>>>>> 4/2/2026 10:52:31 PM ShouldHideHeaderWhenTitleEmpty Stop
Passed ShouldHideHeaderWhenTitleEmpty [1 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.12] Discovering: Controls.TestCases.WinUI.Tests
[xUnit.net 00:00:00.39] Discovered: Controls.TestCases.WinUI.Tests
Test Run Successful.
Total tests: 1
Passed: 1
Total time: 28.1946 Seconds
📁 Fix files reverted (3 files)
eng/pipelines/ci-copilot.ymlsrc/Controls/src/Core/Handlers/Shell/Windows/ShellView.cssrc/Core/src/Platform/Windows/RootNavigationView.cs
|
Apparently according to Claude Opus 4.6, just having |
… the Mac and Windows.
… title. Resaved the test snapshot based on the fix.
633e879 to
2bf6a45
Compare
@kubaflo, I have resolved the merge conflict on this PR. |
…ht space above the tab bar even if the page title is empty (#30382) <!-- 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! ### Root cause The root cause of this issue is that the Windows Shell implementation always reserves space for the header area when Shell.FlyoutBehavior="Flyout" is set, even when pages have no title or header content. The NavigationView control allocates a fixed height above the tab bar for the header region without checking if the current page actually needs this space. This results in an unwanted gap between the flyout toggle area and the tab bar when navigating to pages with empty titles, creating visual inconsistency compared to FlyoutBehavior="Disabled" mode where no header space is reserved for empty content. ### Description of Issue Fix The fix involves adding header visibility logic to the Windows Shell implementation to remove unwanted space above the tab bar in flyout mode. The implementation introduces three key methods in RootNavigationView.cs: UpdateHeaderVisibility() to evaluate header visibility requirements, IsHeaderContentEmpty() to determine if the toolbar contains no title or title view when in flyout mode, and CollapseEmptyHeader() to properly hide empty headers. The toolbar property setter now calls UpdateHeaderVisibility() when the toolbar changes, and ShellView.cs triggers header visibility updates during tab navigation. This ensures empty headers don't occupy unnecessary space in flyout mode while maintaining normal behavior when headers contain content, resolving the spacing issue above the tab bar when switching between pages in Shell applications on Windows. Tested the behavior in the following platforms. - [x] Windows - [x] Mac - [x] iOS - [x] Android ### 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 #30254 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> ### Resaved Test snapshots Resaved the below test snapshot because the ContentPage did not have a title. So, resaved the test snapshot based on the fix. 1. ShellFlowDirectionUpdate 2. VerifyFlyoutBackgroundColor 3. VerifyHamburgerIcon 4. Issue23834FlyoutMisbehavior ### Output | Before Issue Fix | After Issue Fix | |----------|----------| | <video width="270" height="600" src="https://github.com/user-attachments/assets/ca496f96-2500-429f-8720-a8adb7925fce"> | <video width="270" height="600" src="https://github.com/user-attachments/assets/1f0dedd2-4808-46bf-98cf-843ca70294ef"> |
…ent property in MauiToolbar (#35040) <!-- 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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issues Details PR #30382 introduced a call to Toolbar?.HasMenuBarContent was introduced inside RootNavigationView.IsHeaderContentEmpty(), but the HasMenuBarContentproperty was not defined in MauiToolbar, which caused a CS1061 build error on Windows. **Error Details:** error CS1061: 'MauiToolbar' does not contain a definition for 'HasMenuBarContent' and no accessible extension method 'HasMenuBarContent' accepting a first argument of type 'MauiToolbar' could be found (are you missing a using directive or an assembly reference?) ### Description of Change Implemented the missing internal bool HasMenuBarContent property in MauiToolbar.xaml.cs. This property returns true when the toolbar has a non-null MenuBar containing at least one item, ensuring consistency with the existing visibility logic used in SetMenuBar(). ### Fixes Fixes build error introduced by PR #30382 on Windows
…ht space above the tab bar even if the page title is empty (dotnet#30382) <!-- 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! ### Root cause The root cause of this issue is that the Windows Shell implementation always reserves space for the header area when Shell.FlyoutBehavior="Flyout" is set, even when pages have no title or header content. The NavigationView control allocates a fixed height above the tab bar for the header region without checking if the current page actually needs this space. This results in an unwanted gap between the flyout toggle area and the tab bar when navigating to pages with empty titles, creating visual inconsistency compared to FlyoutBehavior="Disabled" mode where no header space is reserved for empty content. ### Description of Issue Fix The fix involves adding header visibility logic to the Windows Shell implementation to remove unwanted space above the tab bar in flyout mode. The implementation introduces three key methods in RootNavigationView.cs: UpdateHeaderVisibility() to evaluate header visibility requirements, IsHeaderContentEmpty() to determine if the toolbar contains no title or title view when in flyout mode, and CollapseEmptyHeader() to properly hide empty headers. The toolbar property setter now calls UpdateHeaderVisibility() when the toolbar changes, and ShellView.cs triggers header visibility updates during tab navigation. This ensures empty headers don't occupy unnecessary space in flyout mode while maintaining normal behavior when headers contain content, resolving the spacing issue above the tab bar when switching between pages in Shell applications on Windows. Tested the behavior in the following platforms. - [x] Windows - [x] Mac - [x] iOS - [x] Android ### 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#30254 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> ### Resaved Test snapshots Resaved the below test snapshot because the ContentPage did not have a title. So, resaved the test snapshot based on the fix. 1. ShellFlowDirectionUpdate 2. VerifyFlyoutBackgroundColor 3. VerifyHamburgerIcon 4. Issue23834FlyoutMisbehavior ### Output | Before Issue Fix | After Issue Fix | |----------|----------| | <video width="270" height="600" src="https://github.com/user-attachments/assets/ca496f96-2500-429f-8720-a8adb7925fce"> | <video width="270" height="600" src="https://github.com/user-attachments/assets/1f0dedd2-4808-46bf-98cf-843ca70294ef"> |
…ht space above the tab bar even if the page title is empty (#30382) <!-- 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! ### Root cause The root cause of this issue is that the Windows Shell implementation always reserves space for the header area when Shell.FlyoutBehavior="Flyout" is set, even when pages have no title or header content. The NavigationView control allocates a fixed height above the tab bar for the header region without checking if the current page actually needs this space. This results in an unwanted gap between the flyout toggle area and the tab bar when navigating to pages with empty titles, creating visual inconsistency compared to FlyoutBehavior="Disabled" mode where no header space is reserved for empty content. ### Description of Issue Fix The fix involves adding header visibility logic to the Windows Shell implementation to remove unwanted space above the tab bar in flyout mode. The implementation introduces three key methods in RootNavigationView.cs: UpdateHeaderVisibility() to evaluate header visibility requirements, IsHeaderContentEmpty() to determine if the toolbar contains no title or title view when in flyout mode, and CollapseEmptyHeader() to properly hide empty headers. The toolbar property setter now calls UpdateHeaderVisibility() when the toolbar changes, and ShellView.cs triggers header visibility updates during tab navigation. This ensures empty headers don't occupy unnecessary space in flyout mode while maintaining normal behavior when headers contain content, resolving the spacing issue above the tab bar when switching between pages in Shell applications on Windows. Tested the behavior in the following platforms. - [x] Windows - [x] Mac - [x] iOS - [x] Android ### 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 #30254 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> ### Resaved Test snapshots Resaved the below test snapshot because the ContentPage did not have a title. So, resaved the test snapshot based on the fix. 1. ShellFlowDirectionUpdate 2. VerifyFlyoutBackgroundColor 3. VerifyHamburgerIcon 4. Issue23834FlyoutMisbehavior ### Output | Before Issue Fix | After Issue Fix | |----------|----------| | <video width="270" height="600" src="https://github.com/user-attachments/assets/ca496f96-2500-429f-8720-a8adb7925fce"> | <video width="270" height="600" src="https://github.com/user-attachments/assets/1f0dedd2-4808-46bf-98cf-843ca70294ef"> |
…ent property in MauiToolbar (#35040) <!-- 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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issues Details PR #30382 introduced a call to Toolbar?.HasMenuBarContent was introduced inside RootNavigationView.IsHeaderContentEmpty(), but the HasMenuBarContentproperty was not defined in MauiToolbar, which caused a CS1061 build error on Windows. **Error Details:** error CS1061: 'MauiToolbar' does not contain a definition for 'HasMenuBarContent' and no accessible extension method 'HasMenuBarContent' accepting a first argument of type 'MauiToolbar' could be found (are you missing a using directive or an assembly reference?) ### Description of Change Implemented the missing internal bool HasMenuBarContent property in MauiToolbar.xaml.cs. This property returns true when the toolbar has a non-null MenuBar containing at least one item, ensuring consistency with the existing visibility logic used in SetMenuBar(). ### Fixes Fixes build error introduced by PR #30382 on Windows
…ht space above the tab bar even if the page title is empty (#30382) <!-- 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! ### Root cause The root cause of this issue is that the Windows Shell implementation always reserves space for the header area when Shell.FlyoutBehavior="Flyout" is set, even when pages have no title or header content. The NavigationView control allocates a fixed height above the tab bar for the header region without checking if the current page actually needs this space. This results in an unwanted gap between the flyout toggle area and the tab bar when navigating to pages with empty titles, creating visual inconsistency compared to FlyoutBehavior="Disabled" mode where no header space is reserved for empty content. ### Description of Issue Fix The fix involves adding header visibility logic to the Windows Shell implementation to remove unwanted space above the tab bar in flyout mode. The implementation introduces three key methods in RootNavigationView.cs: UpdateHeaderVisibility() to evaluate header visibility requirements, IsHeaderContentEmpty() to determine if the toolbar contains no title or title view when in flyout mode, and CollapseEmptyHeader() to properly hide empty headers. The toolbar property setter now calls UpdateHeaderVisibility() when the toolbar changes, and ShellView.cs triggers header visibility updates during tab navigation. This ensures empty headers don't occupy unnecessary space in flyout mode while maintaining normal behavior when headers contain content, resolving the spacing issue above the tab bar when switching between pages in Shell applications on Windows. Tested the behavior in the following platforms. - [x] Windows - [x] Mac - [x] iOS - [x] Android ### 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 #30254 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> ### Resaved Test snapshots Resaved the below test snapshot because the ContentPage did not have a title. So, resaved the test snapshot based on the fix. 1. ShellFlowDirectionUpdate 2. VerifyFlyoutBackgroundColor 3. VerifyHamburgerIcon 4. Issue23834FlyoutMisbehavior ### Output | Before Issue Fix | After Issue Fix | |----------|----------| | <video width="270" height="600" src="https://github.com/user-attachments/assets/ca496f96-2500-429f-8720-a8adb7925fce"> | <video width="270" height="600" src="https://github.com/user-attachments/assets/1f0dedd2-4808-46bf-98cf-843ca70294ef"> |
…ent property in MauiToolbar (#35040) <!-- 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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issues Details PR #30382 introduced a call to Toolbar?.HasMenuBarContent was introduced inside RootNavigationView.IsHeaderContentEmpty(), but the HasMenuBarContentproperty was not defined in MauiToolbar, which caused a CS1061 build error on Windows. **Error Details:** error CS1061: 'MauiToolbar' does not contain a definition for 'HasMenuBarContent' and no accessible extension method 'HasMenuBarContent' accepting a first argument of type 'MauiToolbar' could be found (are you missing a using directive or an assembly reference?) ### Description of Change Implemented the missing internal bool HasMenuBarContent property in MauiToolbar.xaml.cs. This property returns true when the toolbar has a non-null MenuBar containing at least one item, ensuring consistency with the existing visibility logic used in SetMenuBar(). ### Fixes Fixes build error introduced by PR #30382 on Windows
…ht space above the tab bar even if the page title is empty (#30382) <!-- 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! ### Root cause The root cause of this issue is that the Windows Shell implementation always reserves space for the header area when Shell.FlyoutBehavior="Flyout" is set, even when pages have no title or header content. The NavigationView control allocates a fixed height above the tab bar for the header region without checking if the current page actually needs this space. This results in an unwanted gap between the flyout toggle area and the tab bar when navigating to pages with empty titles, creating visual inconsistency compared to FlyoutBehavior="Disabled" mode where no header space is reserved for empty content. ### Description of Issue Fix The fix involves adding header visibility logic to the Windows Shell implementation to remove unwanted space above the tab bar in flyout mode. The implementation introduces three key methods in RootNavigationView.cs: UpdateHeaderVisibility() to evaluate header visibility requirements, IsHeaderContentEmpty() to determine if the toolbar contains no title or title view when in flyout mode, and CollapseEmptyHeader() to properly hide empty headers. The toolbar property setter now calls UpdateHeaderVisibility() when the toolbar changes, and ShellView.cs triggers header visibility updates during tab navigation. This ensures empty headers don't occupy unnecessary space in flyout mode while maintaining normal behavior when headers contain content, resolving the spacing issue above the tab bar when switching between pages in Shell applications on Windows. Tested the behavior in the following platforms. - [x] Windows - [x] Mac - [x] iOS - [x] Android ### 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 #30254 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> ### Resaved Test snapshots Resaved the below test snapshot because the ContentPage did not have a title. So, resaved the test snapshot based on the fix. 1. ShellFlowDirectionUpdate 2. VerifyFlyoutBackgroundColor 3. VerifyHamburgerIcon 4. Issue23834FlyoutMisbehavior ### Output | Before Issue Fix | After Issue Fix | |----------|----------| | <video width="270" height="600" src="https://github.com/user-attachments/assets/ca496f96-2500-429f-8720-a8adb7925fce"> | <video width="270" height="600" src="https://github.com/user-attachments/assets/1f0dedd2-4808-46bf-98cf-843ca70294ef"> |
…ent property in MauiToolbar (#35040) <!-- 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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issues Details PR #30382 introduced a call to Toolbar?.HasMenuBarContent was introduced inside RootNavigationView.IsHeaderContentEmpty(), but the HasMenuBarContentproperty was not defined in MauiToolbar, which caused a CS1061 build error on Windows. **Error Details:** error CS1061: 'MauiToolbar' does not contain a definition for 'HasMenuBarContent' and no accessible extension method 'HasMenuBarContent' accepting a first argument of type 'MauiToolbar' could be found (are you missing a using directive or an assembly reference?) ### Description of Change Implemented the missing internal bool HasMenuBarContent property in MauiToolbar.xaml.cs. This property returns true when the toolbar has a non-null MenuBar containing at least one item, ensuring consistency with the existing visibility logic used in SetMenuBar(). ### Fixes Fixes build error introduced by PR #30382 on Windows
…ht space above the tab bar even if the page title is empty (#30382) <!-- 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! ### Root cause The root cause of this issue is that the Windows Shell implementation always reserves space for the header area when Shell.FlyoutBehavior="Flyout" is set, even when pages have no title or header content. The NavigationView control allocates a fixed height above the tab bar for the header region without checking if the current page actually needs this space. This results in an unwanted gap between the flyout toggle area and the tab bar when navigating to pages with empty titles, creating visual inconsistency compared to FlyoutBehavior="Disabled" mode where no header space is reserved for empty content. ### Description of Issue Fix The fix involves adding header visibility logic to the Windows Shell implementation to remove unwanted space above the tab bar in flyout mode. The implementation introduces three key methods in RootNavigationView.cs: UpdateHeaderVisibility() to evaluate header visibility requirements, IsHeaderContentEmpty() to determine if the toolbar contains no title or title view when in flyout mode, and CollapseEmptyHeader() to properly hide empty headers. The toolbar property setter now calls UpdateHeaderVisibility() when the toolbar changes, and ShellView.cs triggers header visibility updates during tab navigation. This ensures empty headers don't occupy unnecessary space in flyout mode while maintaining normal behavior when headers contain content, resolving the spacing issue above the tab bar when switching between pages in Shell applications on Windows. Tested the behavior in the following platforms. - [x] Windows - [x] Mac - [x] iOS - [x] Android ### 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 #30254 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> ### Resaved Test snapshots Resaved the below test snapshot because the ContentPage did not have a title. So, resaved the test snapshot based on the fix. 1. ShellFlowDirectionUpdate 2. VerifyFlyoutBackgroundColor 3. VerifyHamburgerIcon 4. Issue23834FlyoutMisbehavior ### Output | Before Issue Fix | After Issue Fix | |----------|----------| | <video width="270" height="600" src="https://github.com/user-attachments/assets/ca496f96-2500-429f-8720-a8adb7925fce"> | <video width="270" height="600" src="https://github.com/user-attachments/assets/1f0dedd2-4808-46bf-98cf-843ca70294ef"> |
…ent property in MauiToolbar (#35040) <!-- 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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issues Details PR #30382 introduced a call to Toolbar?.HasMenuBarContent was introduced inside RootNavigationView.IsHeaderContentEmpty(), but the HasMenuBarContentproperty was not defined in MauiToolbar, which caused a CS1061 build error on Windows. **Error Details:** error CS1061: 'MauiToolbar' does not contain a definition for 'HasMenuBarContent' and no accessible extension method 'HasMenuBarContent' accepting a first argument of type 'MauiToolbar' could be found (are you missing a using directive or an assembly reference?) ### Description of Change Implemented the missing internal bool HasMenuBarContent property in MauiToolbar.xaml.cs. This property returns true when the toolbar has a non-null MenuBar containing at least one item, ensuring consistency with the existing visibility logic used in SetMenuBar(). ### Fixes Fixes build error introduced by PR #30382 on Windows
…I test failures on candidate branch (#35312) <!-- 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! ### Root cause PR #30382 introduced AlwaysShowHeader = false in the RootNavigationView constructor to fix Issue #30254 (blank header space in the Shell flyout). However, this was applied unconditionally across all NavigationView display modes. In the scenario from Issue2740 (FlyoutPage with FlyoutBehavior.Locked), the PaneDisplayMode is Left, not LeftMinimal. Because AlwaysShowHeader was set to false, WinUI’s NavigationView collapsed the header whenever the Header became temporarily null during page transitions. As a result, toolbar items (e.g., the Switch button) were removed from the UI Automation tree, causing the test to fail. ### Description of Change The fix updates AlwaysShowHeader dynamically based on the current PaneDisplayMode within the PaneDisplayModeChangedhandler: AlwaysShowHeader = PaneDisplayMode != NavigationViewPaneDisplayMode.LeftMinimal; This ensures: • AlwaysShowHeader = false only for LeftMinimal mode (Shell Flyout), preserving the fix for Issue #30254. • AlwaysShowHeader = true for all other modes (e.g., Left / FlyoutBehavior.Locked), ensuring the header remains visible and toolbar items stay accessible in the UI Automation tree. Also added the updated snapshot for the #30382. ### Issues Fixed - Regression introduced by PR #30382 ### Resaved Test snapshots The below-mentioned test case was resaved because the ContentPage did not have a title. Based on the fix, the currently generated image is the expected image, so the test snapshot has been resaved accordingly, similar to [#30382](#30382). - ModalPageBackgroundShouldBeTransparent **Added snapshots:** Additionally, the updated snapshot for [#30382](#30382) has also been added for the Mac and Windows platforms. - ShouldHideHeaderWhenTitleEmpty - ShouldShowHeaderWhenTitleNotEmpty ### Failure test cases - VerifyFlyoutVerticalScrollModeDisabled - VerifyFlyoutPageToolbarItemsRender - ShouldFlyoutBeVisibleAfterMaximizingWindow - FlyoutItemTextShouldDisplayProperly - VerifyShellMenuItemsAlignedInRTL - TestB43527UpdateTitle - TitleUpdatesAfterShowingNonFlyoutPage - WhenFlyoutIsLockedButtonsAreStillVisible - Issue2740Test - NavigationPageTitle - DoNotAccessDisposedCollectionView
…I test failures on candidate branch (#35340) <!-- 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! Recreates #35312, which was accidentally merged into `inflight/candidate` instead of `inflight/current`. The candidate-side merge was reverted by #35339; this PR re-targets the same fix to `inflight/current`. Original author: @BagavathiPerumal --- ### Root cause PR #30382 introduced AlwaysShowHeader = false in the RootNavigationView constructor to fix Issue #30254 (blank header space in the Shell flyout). However, this was applied unconditionally across all NavigationView display modes. In the scenario from Issue2740 (FlyoutPage with FlyoutBehavior.Locked), the PaneDisplayMode is Left, not LeftMinimal. Because AlwaysShowHeader was set to false, WinUI's NavigationView collapsed the header whenever the Header became temporarily null during page transitions. As a result, toolbar items (e.g., the Switch button) were removed from the UI Automation tree, causing the test to fail. ### Description of Change The fix updates AlwaysShowHeader dynamically based on the current PaneDisplayMode within the PaneDisplayModeChanged handler: AlwaysShowHeader = PaneDisplayMode != NavigationViewPaneDisplayMode.LeftMinimal; This ensures: - AlwaysShowHeader = false only for LeftMinimal mode (Shell Flyout), preserving the fix for Issue #30254. - AlwaysShowHeader = true for all other modes (e.g., Left / FlyoutBehavior.Locked), ensuring the header remains visible and toolbar items stay accessible in the UI Automation tree. Also added the updated snapshot for the #30382. ### Issues Fixed - Regression introduced by PR #30382 ### Resaved Test snapshots The below-mentioned test case was resaved because the ContentPage did not have a title. Based on the fix, the currently generated image is the expected image, so the test snapshot has been resaved accordingly, similar to [#30382](#30382). - ModalPageBackgroundShouldBeTransparent **Added snapshots:** Additionally, the updated snapshot for [#30382](#30382) has also been added for the Mac and Windows platforms. - ShouldHideHeaderWhenTitleEmpty - ShouldShowHeaderWhenTitleNotEmpty ### Failure test cases - VerifyFlyoutVerticalScrollModeDisabled - VerifyFlyoutPageToolbarItemsRender - ShouldFlyoutBeVisibleAfterMaximizingWindow - FlyoutItemTextShouldDisplayProperly - VerifyShellMenuItemsAlignedInRTL - TestB43527UpdateTitle - TitleUpdatesAfterShowingNonFlyoutPage - WhenFlyoutIsLockedButtonsAreStillVisible - Issue2740Test - NavigationPageTitle - DoNotAccessDisposedCollectionView Co-authored-by: BagavathiPerumal <93652794+BagavathiPerumal@users.noreply.github.com>
Note
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!
Root cause
The root cause of this issue is that the Windows Shell implementation always reserves space for the header area when Shell.FlyoutBehavior="Flyout" is set, even when pages have no title or header content. The NavigationView control allocates a fixed height above the tab bar for the header region without checking if the current page actually needs this space. This results in an unwanted gap between the flyout toggle area and the tab bar when navigating to pages with empty titles, creating visual inconsistency compared to FlyoutBehavior="Disabled" mode where no header space is reserved for empty content.
Description of Issue Fix
The fix involves adding header visibility logic to the Windows Shell implementation to remove unwanted space above the tab bar in flyout mode. The implementation introduces three key methods in RootNavigationView.cs: UpdateHeaderVisibility() to evaluate header visibility requirements, IsHeaderContentEmpty() to determine if the toolbar contains no title or title view when in flyout mode, and CollapseEmptyHeader() to properly hide empty headers. The toolbar property setter now calls UpdateHeaderVisibility() when the toolbar changes, and ShellView.cs triggers header visibility updates during tab navigation. This ensures empty headers don't occupy unnecessary space in flyout mode while maintaining normal behavior when headers contain content, resolving the spacing issue above the tab bar when switching between pages in Shell applications on Windows.
Tested the behavior in the following platforms.
Issues Fixed
Fixes #30254
Resaved Test snapshots
Resaved the below test snapshot because the ContentPage did not have a title. So, resaved the test snapshot based on the fix.
Output
BeforeFix.Header.mp4
AfterFix.Header.mp4