Skip to content

February 2nd, Candidate#33779

Open
PureWeen wants to merge 22 commits intomainfrom
inflight/candidate
Open

February 2nd, Candidate#33779
PureWeen wants to merge 22 commits intomainfrom
inflight/candidate

Conversation

@PureWeen
Copy link
Member

@PureWeen PureWeen commented Jan 29, 2026

.NET MAUI inflight/candidate introduces significant improvements across all platforms with focus on quality, performance, and developer experience. This release includes 20 commits with various improvements, bug fixes, and enhancements.

Blazor

CollectionView

DateTimePicker

Dialogalert

Flyout

Fonts

Gestures

Navigation

Picker

SafeArea

Shell

Templates

Theme

Theming

Titlebar

WebView

Xaml

📦 Other (1)
**Full Changelog**: https://github.com/dotnet/maui/compare/main...inflight/candidate

StephaneDelcroix and others added 20 commits January 29, 2026 15:02
<!-- 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

Fixes #33532

When a XAML file contains `NaN` as a value (e.g., `Padding="NaN"`), the
XAML Source Generator was generating invalid C# code using bare `NaN`
instead of `double.NaN`, resulting in:

```
error CS0103: The name 'NaN' does not exist in the current context
```

### Root Cause

The `FormatInvariant()` helper method in `GeneratorHelpers.cs` uses
`SymbolDisplay.FormatPrimitive()` which outputs just `"NaN"` for
`double.NaN` values, without the required type prefix.

### Fix

Updated `FormatInvariant()` to explicitly check for special
floating-point values (`NaN`, `PositiveInfinity`, `NegativeInfinity`)
for both `double` and `float` types, and return the properly qualified
C# literals (e.g., `double.NaN`, `float.PositiveInfinity`).

## Changes

### Modified
- `src/Controls/src/SourceGen/GeneratorHelpers.cs` - Added special
handling for NaN and Infinity values

### Added Tests
- `src/Controls/tests/SourceGen.UnitTests/Maui33532Tests.cs` - 5
SourceGen unit tests for ThicknessConverter with NaN
- `src/Controls/tests/Xaml.UnitTests/Issues/Maui33532.xaml[.cs]` - XAML
unit test for all inflators

## Testing

All new tests pass:
- `ThicknessWithSingleNaNValue` - Tests `Padding="NaN"`
- `ThicknessWithTwoNaNValues` - Tests `Padding="NaN,NaN"`
- `ThicknessWithFourNaNValues` - Tests `Padding="NaN,NaN,NaN,NaN"`
- `ThicknessWithMixedNaNAndRegularValues` - Tests
`Padding="NaN,10,NaN,20"`
- `MarginWithNaNValue` - Tests `Margin="NaN"`
…ow disposal (#33353)

<!-- 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 of Change

Fixes an intermittent `ObjectDisposedException` crash when exiting
MacCatalyst/iOS apps.

**Root cause:** When a window closes, `Window.Destroying()` disposes the
service provider scope, then iOS/MacCatalyst calls
`TraitCollectionDidChange` on view controllers. The override in
`ShellSectionRootRenderer` tried to access disposed services, causing
the crash.

**Architectural improvement:** This PR removes duplicate theme handling
code:
1. **REMOVED** `TraitCollectionDidChange` override from
`ShellSectionRootRenderer` (Controls layer - Shell-specific)
2. **ENHANCED** `TraitCollectionDidChange` in `PageViewController` (Core
layer - applies to ALL pages) with:
- `window?.Handler == null` check to detect window destruction before
accessing services
   - try-catch safety net for race conditions

**Why this approach:**
- Core implementation handles theme changes for all pages (not just
Shell)
- Window.Handler check proactively detects teardown phase (Handler
disconnects before service disposal)
- try-catch provides safety net for potential race conditions
- Eliminates code duplication across layers

**Test added:** `Issue33352` test verifies no crash when
`TraitCollectionDidChange` called after window disposal.

### Issues Fixed

Fixes #33352
```

---

## What Changed from Original

| Section | Original | Recommended | Why |
|---------|----------|-------------|-----|
| **NOTE block** | Missing | Added | Required for user testing |
| **Root cause** | Brief mention | Detailed window disposal sequence | Helps future developers understand timing |
| **Implementation** | "disabled/removed" | Two-part architectural improvement | Accurately describes both removal AND enhancement |
| **PageViewController** | Not mentioned | Detailed enhancement with checks | This is half the fix - must be documented |
| **Rationale** | Not provided | "Why this approach" section | Explains architectural decision |
| **Test** | Not mentioned | Mentioned with test name | Documents test coverage |

---

---------

Co-authored-by: Shane Neuville <shneuvil@microsoft.com>
…ies (#33562)

## Description

Fixes an issue where using source-generated bindable properties (created
via `[BindableProperty]` attribute) in Style Setters would cause the
XAML source generator to fail with error `MAUIG1001: The method or
operation is not implemented`.

## Problem

When a Style Setter references a source-generated bindable property,
`GetBindableProperty()` returns `null` because the property field symbol
is not available the same way as for manually-defined bindable
properties. The code then called `bpRef.ToFQDisplayString()` on a null
reference, causing the failure.

Example XAML that failed:
```xml
<Style x:Key="MyLabelStyle" TargetType="local:MyLabel">
    <Setter Property="MyProperty" Value="Bar" />
</Style>
```

Where `MyProperty` is defined as:
```csharp
public partial class MyLabel : Label
{
    [BindableProperty]
    public partial string MyProperty { get; set; }
}
```

## Solution

Added a fallback mechanism in `SetterValueProvider` that:
1. When `GetBindableProperty()` returns null, parses the property name
from the Setter's `Property` attribute
2. Resolves the target type from the parent Style/Trigger element
3. Uses `HasBindablePropertyHeuristic` to verify a bindable property
exists
4. Constructs the fully-qualified property reference directly (e.g.,
`global::Namespace.MyLabel.MyPropertyProperty`)

## Testing

- All 147 source generator unit tests pass
- Verified with repro project that previously failed now builds
successfully and generates correct code
### Description of Change

Fixes jankiness with using a PanGestureRecognizer to translate a
control.

<!-- Enter description of the fix in this section -->

### Issues Fixed

Fixes #20772

<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->

---------

Co-authored-by: Javier Suárez <javiersuarezruiz@hotmail.com>
Co-authored-by: Shane Neuville <shneuvil@microsoft.com>
…33442)

Removes all `InternalsVisibleTo` attributes that grant the .NET MAUI
Community Toolkit access to internal APIs. This reverts the visibility
changes previously added in PR #29321 while preserving all other
modifications.

### Files Modified

- **src/Controls/src/Xaml/Properties/AssemblyInfo.cs** - Removed 6
CommunityToolkit assembly references
- **src/Controls/src/Core/Properties/AssemblyInfo.cs** - Removed 6
CommunityToolkit assembly references
- **src/Essentials/src/AssemblyInfo/AssemblyInfo.shared.cs** - Removed 5
CommunityToolkit assembly references
- **src/Core/src/Properties/AssemblyInfo.cs** - Removed 5
CommunityToolkit assembly references

Total: 22 InternalsVisibleTo declarations removed for the following
assemblies:
- CommunityToolkit.Maui
- CommunityToolkit.Maui.Core
- CommunityToolkit.Maui.Embedding
- CommunityToolkit.Maui.UnitTests
- CommunityToolkit.Maui.Markup
- CommunityToolkit.Maui.Markup.UnitTests

<!-- START COPILOT CODING AGENT SUFFIX -->



<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>

> I want to remove the InternalsVisibleTo attribute for all the .NET
MAUI Community Toolkit references. We reverted those changes once here:
#29321
> 
> Ignore all the other changes, only add back the removal of the
InternalsVisibleTo. Target the main branch.


</details>



<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jfversluis <939291+jfversluis@users.noreply.github.com>
…#33621)

Syncing with the maui-samples repo:
dotnet/maui-samples#724

Accessibility note (iOS / VoiceOver)
While investigating this issue, it’s worth noting that setting
IsAccessibilityElement = true on the UIViewControllerWrapperView causes
VoiceOver to treat the wrapper as a single accessibility element. As a
result, all child elements (including individual cells) are no longer
exposed to the accessibility tree.

This is expected UIKit behavior:
An accessibility element replaces its children in the VoiceOver
hierarchy.

Therefore, I've removed the SemanticProperties.Description="Tags
Collection"

Fixes #30891
Fixes #30749
…ght when the parent layout changes dynamically, causing incorrect sizing. (#33559)

<!-- 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. !!!!!!!
-->
### Root Cause:

The issue occurs because of Android RecyclerView reusing ViewHolders
with previously measured dimensions and not automatically remeasuring
them when only the layout size changes, causing the EmptyView to retain
its old dimensions instead of adapting to the new available space.

### Fix Description:

The fix involves explicitly forcing the EmptyView to remeasure when the
RecyclerView dimensions change by detecting width or height updates,
locating the corresponding EmptyView ViewHolder, and requesting a layout
pass so it is resized to match the new available space. When the
ViewHolder isn't immediately available, the layout request is deferred
to the next UI loop iteration.

### Issues Fixed
Fixes #33324

### Tested the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Output Screenshot
Before Issue Fix | After Issue Fix |
|----------|----------|
|<video width="100" height="100" alt="Before Fix"
src="https://github.com/user-attachments/assets/fcdb9637-56b8-4dd3-8a23-1dc4e881bb36">|<video
width="100" height="100" alt="After Fix"
src="https://github.com/user-attachments/assets/3ff0bee9-8c80-4d3f-8042-acff1807ece6">|
# PR Changes - MacCatalyst Picker Improvements

Fixes #30897
Fixes #30891

## Overview
Improved MacCatalyst Picker implementation with proper focus management

## Changes Made

### 1. **PickerHandler.iOS.cs** - MacCatalyst-specific improvements

#### Added UIAlertController instance field
- Declared `UIAlertController? pickerController` as an instance field to
enable proper dismissal via `Unfocus` command
- Allows external code to programmatically close the picker dialog

#### Improved picker dismiss logic
- Moved picker dismiss logic from event handler to the "Done" button
action
- Removed `EditingDidEnd` event handler that was causing duplicate
dismiss calls
- Simplified focus state management by handling it directly in the Done
action

#### Added MapUnfocus command handler
- Implemented `MapUnfocus` method for MacCatalyst to programmatically
dismiss the picker
- Properly updates `IsFocused` and `IsOpen` states when dismissed
- Includes null checks for safety

### 2. **PickerHandler.cs** - Command mapper registration

#### Registered Unfocus command for MacCatalyst
- Added `#elif MACCATALYST` section to CommandMapper
- Registered `nameof(IPicker.Unfocus)` command to enable programmatic
picker dismissal on MacCatalyst
- Brings MacCatalyst picker behavior in line with Android implementation

## Testing
Issue2339

## Platforms Affected
- **MacCatalyst** (primary)
- iOS (no behavior changes, shared code)

## Breaking Changes
None - this is purely an implementation improvement with no API changes.
…dictive Back Gesture Changes (#33213)

<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Issue Description

BlazorWebView back navigation stopped working in .NET 10 on Android.
When the user presses the back button while viewing a BlazorWebView with
navigable history, the entire page is popped instead of navigating back
within the WebView content

### RootCause 

The AndroidLifecycle.OnBackPressed lifecycle event system introduced for
Android 13+ predictive back gesture support intercepts back navigation.
Since BlazorWebView doesn't register a handler to check
WebView.CanGoBack(), the system pops the entire page instead of allowing
the WebView to navigate its internal history first, breaking the back
navigation behavior that worked in .NET 9.

### Description of Change

PR #32461 introduced distributed back navigation handling for Android
13+ predictive back gesture support. This PR extends that implementation
to include BlazorWebView

**BlazorWebViewHandler.Android.cs:** 

Added an `AndroidLifecycle.OnBackPressed` handler in ConnectHandler. The
handler checks `WebView.CanGoBack()` to determine whether the
BlazorWebView maintains internal navigation history. If history exists,
it calls `WebView.GoBack()` and returns true, ensuring the user
navigates backwards within the WebView instead of closing the page. If
no internal history exists, it returns false, allowing the standard MAUI
navigation stack to handle the back action.

**LifecycleEventService.cs**: 

Added `RemoveEvent<TDelegate>` method to properly cleanup lifecycle
event handlers and prevent memory leaks when handlers are disconnected.

### Issues Fixed
Fixes #32767 

### Tested the behaviour on the following platforms
- [x] Android
- [ ] Windows
- [ ] iOS
- [ ] Mac

 
### Output Screenshot
Before Issue Fix | After Issue Fix |
|----------|----------|
|<video width="300" height="150" alt="Before Fix"
src="https://github.com/user-attachments/assets/0d6550f8-115a-4893-bb0c-ee24bff38378">|<video
width="300" height="150" alt="After Fix"
src="https://github.com/user-attachments/assets/49bf38a5-f7be-4790-8fbb-b29ab96b1ed3">|

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Stephane Delcroix <stephane@delcroix.org>
Co-authored-by: Subhiksha Chandrasekaran <subhiksha.c@syncfusion.com>
<!-- 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. !!!!!!!
-->

### Root Cause of the Issue:
- In WinUI, the theme can only be set when the app is started, not while
it's running. On the .NET MAUI side, we explicitly update control colors
according to the defined styles for the respective theme. As a result,
colors were updated correctly for the controls we handled explicitly.

- However, controls where we did not explicitly set the colors (e.g.,
DatePicker/TimePicker backgrounds, Checkbox tick marks, and TitleBar
colors) were not updated properly when the theme changed.

- This happens because WinUI default colors are tied to the theme at the
time the app is launched. For example, if the app starts in Light theme,
the WinUI theme is initialized as Light and its colors are applied for
the entire lifecycle. These defaults are not refreshed when the theme
changes at runtime.

- Due to this limitation, theme-related colors (including TitleBar
color) were not updated as expected.

### Description of Change

- Implemented a common logic to apply the appropriate theme by setting
the RequestedTheme on the root view of the Window. This approach is
consistent with what is used in the WinUI Gallery repo.

- With this change, theme-related colors are correctly refreshed across
all child views, resolving both theming inconsistencies and the TitleBar
color issue when the app theme is changed.

### Reference: 
- The implementation is based on the following references. Additionally,
there is a known issue in WinUI where updating the theme at runtime does
not refresh the TitleBar caption button colors, which requires manual
handling.

- **Updating Root View RequestedTheme:**
https://github.com/microsoft/WinUI-Gallery/blob/96dc185a3a3e488f820d06579d85cb4f480a7089/WinUIGallery/Helpers/ThemeHelper.cs#L62
- **AppWindow TitleBar doesn't update caption button colors correctly
when changed while app is running:**
https://github.com/microsoft/WinUI-Gallery/blob/96dc185a3a3e488f820d06579d85cb4f480a7089/WinUIGallery/Helpers/TitleBarHelper.cs#L22


### Screenshot

| Before Fix | After Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/0db22e18-cbcc-4cdc-857e-c1b093497309">
| <video
src="https://github.com/user-attachments/assets/2e53efce-4122-4179-93aa-c549ded74878">
|




### 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 #12507
Fixes #22058
Fixes #30518 (Windows)
Fixes #30807
Fixes #31819

<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->

---------

Co-authored-by: Vignesh-SF3580 <vignesh.nagarajan@syncfusion.com>
…ti-range delegate (#33616)

<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Issue Details
On iOS 26, DisplayPromptAsync ignores the maxLength parameter, allowing
users to enter an unlimited number of characters beyond the specified
limit.

### Root Cause
iOS 26 introduced a new delegate method, ShouldChangeCharactersInRanges,
which accepts multiple text ranges instead of the older
ShouldChangeCharacters method. On iOS 26, the old delegate is no longer
invoked, causing MAUI’s maxLength enforcement to break.

### Description of Change
A runtime version check was added to use the
ShouldChangeCharactersInRanges delegate on iOS 26 and later, and the
ShouldChangeCharacters delegate on earlier iOS versions. The new
delegate calculates the total text length by summing all range lengths
and validating the result against maxLength.

Validated the behavior in the following platforms
 
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac
 
### Issues Fixed
  
Fixes #33549   

### Test case
In the test for DisplayPromptAsync, there is no supported way to type
text into the display prompt text fields using Appium.

### Output  ScreenShot

|Before|After|
|--|--|
| <video
src="https://github.com/user-attachments/assets/e9c48ea5-1dc8-42da-a5a2-b7de13df39cd"
>| <video
src="https://github.com/user-attachments/assets/5324954b-d4dd-4013-a3c8-3f5c34a845cf">|
<!-- 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 of Change

Fixed application crash when dragging an element to the end of a
CollectionView with a header on Android.

**Root cause:** Android's RecyclerView adapter includes the header at
position 0, offsetting all item positions by 1. When reordering items,
the code was using adapter positions directly to access the ItemsSource
(which doesn't include the header), causing an
ArgumentOutOfRangeException.

**Fix:** Added header offset calculation when accessing ItemsSource
indices:
- Uses existing `itemsSource.HasHeader` property to detect header
presence
- Calculates source indices by subtracting 1 from adapter positions when
header is present
- Mirrors the existing pattern used for grouped CollectionView (lines
33-38)

**Key insight:** RecyclerView adapter indices (includes header) ≠
ItemsSource indices (items only). Must translate between these two index
spaces when reordering.

**Files changed:**
- `ReorderableItemsViewAdapter.cs` - Added header offset calculation (+7
-3 lines)
- Test files - Added UI tests to verify fix prevents crash

### Issues Fixed

Fixes #17823

---

## Comparison with Current Description

### Current (Minimal but Accurate)
```markdown
### Description of Change

Fixed application crash when dragging an element to the end of a collection on Android.

### Issues Fixed

Fixes #17823
```

### What's Added
1. ✅ **Required NOTE block** - Enables community testing of artifacts
2. ✅ **Root cause explanation** - Helps future maintainers understand
why the bug occurred
3. ✅ **Fix approach details** - Documents the solution pattern for
similar issues
4. ✅ **Key insight** - Captures the fundamental concept (index space
translation)
5. ✅ **File changes summary** - Quick overview of what was modified

### Why This Matters
- **For future agents**: Clear context about the adapter vs. source
index pattern
- **For community**: Ability to test artifacts before merge
- **For maintainers**: Understanding of the fix without reading code
- **For similar issues**: Pattern to follow (already used for grouped
CollectionView)

---

## Usage

Copy the "Enhanced Description with Context" section above and paste it
into the PR description on GitHub.

The current description is functionally correct - this enhancement adds
valuable context without changing accuracy.

---------

Co-authored-by: vitvov <vitvov@hotmail.com>
Co-authored-by: Gerald Versluis <gerald.versluis@microsoft.com>
Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com>
…r popups (#33152)

<!-- 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 of Change

This PR fixes VoiceOver accessibility on iOS for Picker, DatePicker, and
TimePicker controls. When picker popups open/close, VoiceOver now
properly shifts focus using iOS accessibility notifications.

**Root cause:** VoiceOver on iOS requires explicit focus notifications
via `UIAccessibility.PostNotification(ScreenChanged, view)` when modal
UI appears or dismisses. Without these notifications, VoiceOver doesn't
know to shift focus, leaving users navigating background controls
instead of the picker popup.

**Fix:** 
- Adds `PostAccessibilityFocusNotification()` extension methods in
`SemanticExtensions.cs`
- Posts `ScreenChanged` notification when picker popups open (in
`EditingDidBegin` event)
- Posts `ScreenChanged` notification to restore focus when popups close
(in `EditingDidEnd` event)
- Handles edge cases: null window checks, main thread dispatch for
delayed InputView availability

**Tests:** UI tests created in `Issue30746.xaml[.cs]` and marked with
`ManualReview` category since VoiceOver focus cannot be automated with
Appium. Manual testing with VoiceOver enabled confirms proper focus
behavior.

### Issues Fixed

Fixes #30746
…l) (#33526)

<!-- 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

In `MauiView.GetAdjustedSafeAreaInsets()` on iOS, views that don't
implement `ISafeAreaView` or `ISafeAreaView2` (such as
`ContentPresenter`, `Border`) were falling through to return
`baseSafeArea`. This applied full device safe area insets to views that
never opted into safe area handling, causing double-padding when used
inside ControlTemplates.

### Description of Change

Changed the fallback behavior in `GetAdjustedSafeAreaInsets()` to return
`SafeAreaPadding.Empty` instead of `baseSafeArea` for views that don't
implement `ISafeAreaView` or `ISafeAreaView2`.

**This is a philosophy change:**
- **Before:** Safe area applied by default (opt-out model)
- **After:** Safe area only applies to views that implement the
interfaces (opt-in model)

This aligns iOS with Android, where
`SafeAreaExtensions.GetSafeAreaView2()` returns `null` for non-safe-area
views.

### Key Technical Details

**Safe area interfaces (opt-in contract):**
- `ISafeAreaView` - Legacy interface with `IgnoreSafeArea` property
- `ISafeAreaView2` - Modern interface with per-edge `SafeAreaRegions`
control

**Views that implement these interfaces (safe area works):**
- `ContentPage`, `ContentView`, `Layout`, `ScrollView`, `Border`, `Page`

**Views that don't (now return Empty):**
- `ContentPresenter`, custom views without interface, third-party
controls

### What NOT to Do (for future agents)

- ❌ **Don't use Element type in Platform layer** -
`src/Core/src/Platform/` cannot reference Controls-layer types like
`Element`. Use `IView`, `ISafeAreaView`, `ISafeAreaView2` only.
- ❌ **Don't use type name string matching** - Checking
`View.GetType().Name.Contains("ContentPresenter")` is brittle
- ❌ **Don't check ancestor hierarchy for safe area** - Performance cost
and wrong abstraction (safe area is per-edge, not binary)

### Edge Cases

| Scenario | Risk | Mitigation |
|----------|------|------------|
| Legacy layouts (`LegacyLayouts/`) | Low | Already `[Obsolete]` |
| Custom views without ISafeAreaView | Medium | Implement interface to
opt-in |
| GraphicsView/WebView as root | Low | Parent ContentPage handles safe
area |

### Issues Fixed

Fixes #33458

### Platforms Tested

- [x] iOS
- [x] Android  
- [ ] Windows (no SafeAreaEdges implementation)
- [ ] Mac (no SafeAreaEdges implementation)

### Screenshots

| Before Fix | After Fix |
|------------|-----------|
| <img width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/3bd10b79-6472-4e86-b717-d433b56f1f82"
/> | <img width="350" alt="withfix"
src="https://github.com/user-attachments/assets/d30e8c0c-3918-4528-bbd2-6fb3bba8d766"
/> |
### Description of Change
This PR hides obsolete FontSize named values (like "Large", "Medium",
"Small", etc.) from IDE autocomplete suggestions in XAML.

The named font size values have been marked
[obsolete](https://learn.microsoft.com/en-us/dotnet/api/microsoft.maui.controls.namedsize?view=net-maui-9.0)
since .NET 9. However, the design-time type converter was still
suggesting these values in the IDE's IntelliSense, leading users to use
them and then receive "Obsolete" warnings - especially when using XAML
source generation (MauiXamlInflator=SourceGen).

The fix overrides `GetStandardValuesSupported()` to return false and
`GetStandardValues()` to return an empty collection in
`FontSizeDesignTypeConverter`. This prevents the IDE from suggesting the
obsolete named font size values while still allowing them to be used
(with appropriate obsolete warnings) for backward compatibility.

### Issues Fixed

#33560

see also: #33623

---------

Co-authored-by: Kirill Ovchinnikov <kovchinnikov@microsoft.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…nresponsive (#33256)

<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Issue Details
On Windows, when TitleBar.IsVisible is set to false, the system caption
buttons (minimize, maximize, close) become unresponsive after resizing
the window.

### Description of Change

<!-- Enter description of the fix in this section -->
Updated WindowRootView.UpdateTitleBarContentSize() to apply passthrough
regions only when the TitleBar is visible and to clear them when it is
hidden, preventing stale regions from blocking caption button
interactions.

### 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 #33171 

<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->

**Tested the behavior in the following platforms.**
- [ ] Android
- [x] Windows
- [ ] iOS
- [ ] Mac

| Before  | After  |
|---------|--------|
| **Windows**<br> <video
src="https://github.com/user-attachments/assets/6b30d580-ea49-4b5d-9e4c-f6db75897d5d"
width="600" height="300"> | **Windows**<br> <video
src="https://github.com/user-attachments/assets/52f04718-3f2e-4d5e-985b-72efac175af7"
width="600" height="300"> |

---------

Co-authored-by: Shane Neuville <shane94@hotmail.com>
)

<!-- 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 of Change

Footer position calculation in
`ShellFlyoutContentRenderer.UpdateFooterPosition()` did not account for
`SafeAreaInsets.Bottom`, causing footers with horizontal `StackLayout`
to render below the visible area.

```csharp
// Before
_footerView.Frame = new CGRect(0, View.Frame.Height - footerHeight, footerWidth, footerHeight);

// After
var footerY = View.Frame.Height - footerHeight - View.SafeAreaInsets.Bottom;
_footerView.Frame = new CGRect(0, footerY, footerWidth, footerHeight);
```

Also enabled horizontal orientation in `HeaderFooterShellFlyout` test
case that was previously commented out due to this bug.

### Issues Fixed

Fixes #26395

> [!WARNING]
>
> <details>
> <summary>Firewall rules blocked me from connecting to one or more
addresses (expand for details)</summary>
>
> #### I tried to connect to the following addresses, but was blocked by
firewall rules:
>
> - `4zjvsblobprodcus390.vsblob.vsassets.io`
> - Triggering command: `/home/REDACTED/work/maui/maui/.dotnet/dotnet
dotnet restore
src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj`
(dns block)
>
> If you need me to access, download, or install something from one of
these locations, you can either:
>
> - Configure [Actions setup
steps](https://gh.io/copilot/actions-setup-steps) to set up my
environment, which run before the firewall is enabled
> - Add the appropriate URLs or hosts to the custom allowlist in this
repository's [Copilot coding agent
settings](https://github.com/kubaflo/maui/settings/copilot/coding_agent)
(admins only)
>
> </details>

<!-- START COPILOT CODING AGENT SUFFIX -->



<details>

<summary>Original prompt</summary>

> can you please work on this
#26395


</details>


> **Custom agent used: issue-resolver**
> Specialized agent for investigating and resolving community-reported
.NET MAUI issues through hands-on testing and implementation



<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.
)

Fixes #28570
Fixes #33139

(I poked around a bit and I think there is indeed an issue in MAUI here.
When a control is added to the visual tree, MAUI checks the parent’s
BackButtonBehavior and propagates it to the child. The problem is that,
at that point, the Command is not yet assigned, so the propagated
behavior ends up in an incomplete state.

Because BackButtonBehavior depends on bindings and command resolution,
its propagation is more complex than that of simple properties. For this
reason, it probably shouldn’t be propagated automatically in the same
way as other properties.)

> [!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!

## Summary

This PR provides an **alternative solution** to issue #28570, which was
previously fixed via property propagation in PR #28615. The issue:
setting `BackButtonBehavior` with `IsVisible="False"` or
`IsEnabled="False"` on a Shell in XAML doesn't work - the back button
still appears.

**This alternative approach uses explicit fallback lookup instead of
automatic property propagation**, making the behavior more predictable
and avoiding side effects.

**Quick verification:**
- ✅ Tested on Android - Issue resolved
- ✅ Tested on iOS - Issue resolved  
- ✅ UI tests passing (existing Issue28570 test)
- ✅ No propagation side effects

<details>
<summary><b>📋 Click to expand full PR details</b></summary>

## Problem Statement

When a user sets `BackButtonBehavior` on a `Shell` in XAML:

```xml
<Shell>
    <Shell.BackButtonBehavior>
        <BackButtonBehavior IsVisible="False"/>
    </Shell.BackButtonBehavior>
    <!-- Shell content -->
</Shell>
```

The back button should be hidden on all child pages, but it still
appears. The `BackButtonBehavior` set on the Shell is not being applied
to navigated pages.

---

## Original Fix (PR #28615)

The merged PR #28615 solved this by adding `BackButtonBehaviorProperty`
to the property propagation system in
`PropertyPropagationExtensions.cs`:

```csharp
if (propertyName == null || propertyName == Shell.BackButtonBehaviorProperty.PropertyName)
    BaseShellItem.PropagateFromParent(Shell.BackButtonBehaviorProperty, element);
```

**How it works**: Automatically propagates `BackButtonBehavior` from
parent (Shell) to child (Page) through the property propagation
infrastructure.

**Issues with this approach**:
1. **Hidden magic**: Developers don't expect attached properties to
propagate automatically
2. **BindingContext conflicts**: Propagation can cause `BindingContext`
inheritance issues (as seen in the Sandbox app testing)
3. **Performance**: Checks and propagates on every property change event
4. **Complexity**: Relies on the property propagation system which is
already complex

---

## Alternative Solution (This PR)

Instead of automatic propagation, this PR implements **explicit fallback
lookup**:

### New Method: `GetEffectiveBackButtonBehavior()`

```csharp
internal static BackButtonBehavior GetEffectiveBackButtonBehavior(BindableObject page)
{
    if (page == null)
        return null;

    // First check if the page has its own BackButtonBehavior
    var behavior = GetBackButtonBehavior(page);
    if (behavior != null)
        return behavior;

    // Fallback: check if the Shell itself has a BackButtonBehavior
    if (page is Element element)
    {
        var shell = element.FindParentOfType<Shell>();
        if (shell != null)
        {
            behavior = GetBackButtonBehavior(shell);
            if (behavior != null)
                return behavior;
        }
    }

    return null;
}
```

### How It Works

1. **Check page first**: Look for `BackButtonBehavior` on the page
itself
2. **Check Shell if not found**: Walk up the tree to find the parent
Shell and check its `BackButtonBehavior`
3. **Return what's found**: First match wins (page overrides Shell)

### Where It's Used

All call sites that previously used `GetBackButtonBehavior()` now use
`GetEffectiveBackButtonBehavior()`:

**Cross-platform**:
- `Shell.OnBackButtonPressed()` - Windows back button handling
- `ShellToolbar.UpdateBackbuttonBehavior()` - Toolbar updates

**Android**:
- `ShellToolbarTracker.OnClick()` - Back button click
- `ShellToolbarTracker.SetPage()` - Page changes
- `ShellToolbarTracker.OnPagePropertyChanged()` - Property updates
- `ShellToolbarTracker.UpdateDrawerArrowFromBackButtonBehavior()` -
Drawer arrow
- `ShellToolbarTracker.UpdateToolbarIconAccessibilityText()` -
Accessibility

**iOS**:
- `ShellSectionRenderer` - Back button in navigation
- `ShellPageRendererTracker.OnPagePropertyChanged()` - Property updates
- `ShellPageRendererTracker.UpdateToolbar()` - Toolbar updates

---

## Advantages of Alternative Approach

| Aspect | Propagation (Original) | Fallback Lookup (This PR) |
|--------|----------------------|---------------------------|
| **Predictability** | Hidden, automatic | Explicit, clear intent |
| **BindingContext** | Can cause conflicts | No interference |
| **Performance** | Checks on every property change | Only checks when
needed |
| **Debugging** | Hard to trace | Easy to follow |
| **Mental Model** | "Magic happens" | "Check page, then Shell" |
| **Side Effects** | Propagation system interactions | None |

### Specific Benefits

1. **No BindingContext Issues**: Avoids the propagation-related
`BindingContext` inheritance problems
2. **Clearer Intent**: The code explicitly says "get from page, or fall
back to Shell"
3. **Better Performance**: Only performs lookup when
`BackButtonBehavior` is actually needed
4. **Easier Maintenance**: No coupling with property propagation
infrastructure
5. **Simpler Mental Model**: Developers can understand the lookup logic
without knowing propagation internals

---

## Root Cause

The original issue existed because Shell's back button handling code
only checked the current page for `BackButtonBehavior`:

```csharp
var backButtonBehavior = GetBackButtonBehavior(GetVisiblePage());
```

If the page didn't have a `BackButtonBehavior` set, it would return
`null`, even though the Shell had one defined. The code had no fallback
mechanism.

---

## Testing

### Before Fix

Setting `BackButtonBehavior` on Shell:
```xml
<Shell>
    <Shell.BackButtonBehavior>
        <BackButtonBehavior IsVisible="False" TextOverride="BackButton"/>
    </Shell.BackButtonBehavior>
</Shell>
```

**Result**: Back button still visible ❌

### After Fix

Same XAML code.

**Result**: Back button hidden ✅

### Test Evidence

```bash
# Run Issue28570 test
pwsh .github/scripts/BuildAndRunHostApp.ps1 -Platform android -TestFilter "Issue28570"

# Output:
# >>>>> BackButtonShouldNotBeVisible Start
# >>>>> BackButtonShouldNotBeVisible Stop
# Passed BackButtonShouldNotBeVisible [1 s]
# ✅ All tests passed
```

The test verifies:
1. Navigate to detail page
2. Back button should NOT be visible (because Shell has
`IsVisible="False"`)
3. Test uses `App.WaitForNoElement("BackButton")` to confirm

---

## Files Changed

### Core Changes

**`src/Controls/src/Core/Shell/Shell.cs`**
- ➕ Added `GetEffectiveBackButtonBehavior()` method (lines 200-225)
- ✏️ Modified `OnBackButtonPressed()` to use new method (line 1570)

**`src/Controls/src/Core/Internals/PropertyPropagationExtensions.cs`**
- ➖ Removed `BackButtonBehaviorProperty` propagation (lines 44-45)

**`src/Controls/src/Core/ShellToolbar.cs`**
- ✏️ Modified `UpdateBackbuttonBehavior()` to use new method (line 134)

### Platform-Specific Changes

**Android** -
`src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellToolbarTracker.cs`
- ✏️ Updated 5 call sites to use `GetEffectiveBackButtonBehavior()`
  - `OnClick()` (line 162)
  - `SetPage()` (line 258)
  - `OnPagePropertyChanged()` (line 312)
  - `UpdateDrawerArrowFromBackButtonBehavior()` (line 410)
  - `UpdateToolbarIconAccessibilityText()` (line 543)

**iOS** - Platform-specific handlers
- ✏️ `ShellSectionRenderer.cs` (line 152)
- ✏️ `ShellPageRendererTracker.cs` (lines 136, 216)

**Total**: 8 files changed, 11 call sites updated

---

## Edge Cases Tested

✅ **BackButtonBehavior on Shell only**: Works (this is the fix)
✅ **BackButtonBehavior on Page only**: Works (page takes precedence)
✅ **BackButtonBehavior on both**: Page overrides Shell (expected
behavior)
✅ **No BackButtonBehavior anywhere**: Returns `null` (graceful fallback)
✅ **Multiple navigation levels**: Each page correctly looks up to Shell

---

## Breaking Changes

**None**. This is a pure bug fix that makes the documented behavior work
correctly.

**API Surface**: No public API changes. The new method is `internal`.

**Behavior Changes**: 
- ✅ Previously broken: Setting `BackButtonBehavior` on Shell had no
effect
- ✅ Now works: Shell's `BackButtonBehavior` applies to child pages as
expected

---

## Comparison with Original PR #28615

| | PR #28615 (Propagation) | This PR (Fallback Lookup) |
|---|---|---|
| **Lines Changed** | +3 lines | +30 lines |
| **Approach** | Add to propagation list | Explicit lookup method |
| **Call Sites Modified** | 0 | 11 |
| **BindingContext Safe** | ⚠️ Can cause issues | ✅ No side effects |
| **Performance** | Checks on all property changes | Only checks when
needed |
| **Testability** | Implicit behavior | Explicit behavior |
| **Maintainability** | Coupled to propagation | Standalone |

While the propagation approach is simpler in terms of lines changed,
this alternative provides:
- Better separation of concerns
- No hidden side effects
- More explicit and predictable behavior
- Easier to debug and maintain long-term

---

## Migration Notes

**For users**: No code changes needed. This fix makes the existing,
documented API work correctly.

**For maintainers**: If modifying back button handling, use
`GetEffectiveBackButtonBehavior()` instead of `GetBackButtonBehavior()`
to ensure Shell fallback works.

---

## Test Coverage

**Existing test reused**: `Issue28570` test already exists from PR
#28615 and passes with this alternative fix.

**Test location**:
- HostApp: `src/Controls/tests/TestCases.HostApp/Issues/Issue28570.cs`
- NUnit:
`src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue28570.cs`

The test:
1. Creates Shell with `BackButtonBehavior` having `IsVisible="False"`
2. Navigates to detail page
3. Verifies back button is NOT visible using
`App.WaitForNoElement("BackButton")`

---

## Related Issues

- #28570 - Original issue (this PR fixes)
- PR #28615 - Original fix via propagation (this PR provides
alternative)

---

## Screenshots/Evidence

### Test Output

```
🔹 Running UI tests with filter: Issue28570

>>>>> BackButtonShouldNotBeVisible Start
>>>>> BackButtonShouldNotBeVisible Stop

✅ All tests passed

╔═══════════════════════════════════════════════╗
║              Test Summary                     ║
╠═══════════════════════════════════════════════╣
║  Platform:     ANDROID                        ║
║  Test Filter:  Issue28570                     ║
║  Result:       SUCCESS ✅                     ║
╚═══════════════════════════════════════════════╝
```

</details>

---

## Recommendation

This alternative fix provides a cleaner, more maintainable solution to
issue #28570. While the original PR #28615's propagation approach works,
this explicit fallback approach:

- ✅ Avoids propagation side effects
- ✅ Makes the code more understandable
- ✅ Provides better long-term maintainability
- ✅ Solves the same issue with the same test passing

**Suggested action**: Replace PR #28615 with this alternative approach
for the reasons outlined above.
…3726)

> [!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

Fixes JavaScript string escaping in `WebViewHelper.EscapeJsString` to
properly handle both backslashes and single quotes.

### Changes
- Escape backslashes **before** single quotes (order matters for
`eval()`)
- Prevents potential injection issues when passing strings to JavaScript
- Updated unit tests to cover backslash escaping scenarios

## Testing
- Unit tests added/updated in `WebViewHelperTests.cs`

---------

Co-authored-by: Shane Neuville <shane94@hotmail.com>
<!-- 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 Shell routing system allowed duplicate routes to be registered for
sibling elements (e.g., two ShellContent items in the same ShellSection
with route "MapPage"). This caused confusing navigation behavior where
`OnNavigatedTo` would not be called when navigating between pages with
duplicate routes.

The user discovered this was the root cause of issue #14000 and
requested that MAUI throw an exception when duplicate routes are
detected, to prevent this confusing scenario.

### Description of Change

Added **sibling-based duplicate route validation**:

1. **`Routing.ValidateForDuplicates(Element, string)`** - New validation
method that:
- Checks if a route is already assigned to a sibling element (elements
with same parent)
- Allows same route at different hierarchy levels (e.g., `//one/content`
and `//two/content`)
- Throws `ArgumentException` with clear error message when duplicate
found

2. **`BaseShellItem.Route` property setter** - Now calls validation
before setting route

3. **5 comprehensive unit tests** - Verify:
   - Duplicate sibling routes throw exception
   - Same route in different parents is allowed (hierarchical routing)
   - Changing/removing routes frees them for reuse
   - Reassigning same route to same element is idempotent

4. **Cleanup** - Removed duplicate `AddTopTab()` call in Issue6878 test
that would now throw

**This is a philosophy change:**
- **Before:** Duplicate routes silently accepted, caused confusing
behavior
- **After:** Duplicate sibling routes rejected immediately with clear
error message

### Key Technical Details

**Sibling-based validation:**
- Only checks duplicates among elements with the same parent
(`element.Parent.LogicalChildrenInternal`)
- Respects Shell's hierarchical routing structure
- No global state needed

**Why sibling-based, not global?**
- Shell supports hierarchical routing where same route can exist at
different levels
- Example: `//route1/content` and `//route2/content` are both valid
- Global tracking would incorrectly reject this valid scenario

### What NOT to Do (for future agents)

- ❌ **Don't use global route tracking (HashSet<string>)** - Breaks
Shell's hierarchical routing. Reviewers rejected this approach because
same route at different hierarchy levels is valid.
- ❌ **Don't use ConcurrentDictionary or shared state** - Not thread-safe
and causes lifecycle issues (routes never removed when elements deleted)
- ❌ **Don't validate at Shell level** - Validation must be at
BaseShellItem.Route setter for immediate feedback

### Issues Fixed

Fixes #14000

### Tested the behavior in the following platforms

- [x] Windows
- [x] Android
- [x] iOS
- [x] Mac

---------

Co-authored-by: Stephane Delcroix <stephane@delcroix.org>
Copilot AI review requested due to automatic review settings January 29, 2026 21:04
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR is a broad “candidate” bundle that updates several MAUI subsystems (Shell/navigation, safe-area handling, Windows theming/title bar behavior, Android/BlazorWebView back navigation), plus XAML source-gen fixes and new/updated tests/assets.

Changes:

  • Improves platform behavior: iOS/MacCatalyst accessibility & lifecycle safety, Windows title bar interactions/theme propagation, Android gesture/back-navigation handling.
  • Updates Shell routing/back-button behavior logic (duplicate route validation; effective BackButtonBehavior lookup).
  • Expands test coverage and baselines (new unit/UI tests, WinUI snapshot images, XAML/source-gen tests).

Reviewed changes

Copilot reviewed 74 out of 110 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
src/TestUtils/src/UITest.Appium/HelperExtensions.cs Adds Windows caption button helpers for WinUI/Appium UI tests.
src/Templates/src/templates/maui-mobile/Pages/ProjectDetailPage.xaml Template tweak to tag selection UI (removes a semantic description).
src/Essentials/src/AssemblyInfo/AssemblyInfo.shared.cs Removes InternalsVisibleTo entries for CommunityToolkit assemblies.
src/Core/src/Properties/AssemblyInfo.cs Removes InternalsVisibleTo entries for CommunityToolkit assemblies.
src/Core/src/Platform/iOS/SemanticExtensions.cs Adds iOS VoiceOver focus notification helpers.
src/Core/src/Platform/iOS/PageViewController.cs Avoids theme updates during teardown; guards disposed service access.
src/Core/src/Platform/iOS/MauiView.cs Adjusts safe-area fallback behavior (legacy ISafeAreaView path).
src/Core/src/Platform/Windows/WindowRootView.cs Adjusts passthrough regions behavior when title bar is hidden.
src/Core/src/Platform/Windows/MauiWinUIWindow.cs Refactors event handlers; alters title bar button color updates.
src/Core/src/LifecycleEvents/LifecycleEventService.cs Adds lifecycle handler removal API (currently internal).
src/Core/src/Handlers/WebView/WebViewHelper.cs Reworks JS string escaping (handles backslashes and line terminators).
src/Core/src/Handlers/TimePicker/TimePickerHandler.iOS.cs Posts VoiceOver focus notifications for TimePicker open/close.
src/Core/src/Handlers/Picker/PickerHandler.iOS.cs Improves MacCatalyst Picker dismissal/unfocus + VoiceOver focus behavior.
src/Core/src/Handlers/Picker/PickerHandler.cs Adds MacCatalyst Unfocus mapping.
src/Core/src/Handlers/DatePicker/DatePickerHandler.iOS.cs Posts VoiceOver focus notifications for DatePicker open/close.
src/Controls/tests/Xaml.UnitTests/Issues/Maui33532.xaml.cs Adds XAML unit test for NaN values generating valid code.
src/Controls/tests/Xaml.UnitTests/Issues/Maui33532.xaml Adds XAML content reproducing NaN parsing/source-gen issue.
src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyTitleBarBackgroundColorChange.png Adds/updates WinUI visual baseline.
src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/ToolbarItemsShouldBeVisible.png Adds/updates WinUI visual baseline.
src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/EntryClearButtonColorShouldUpdateOnThemeChange.png Adds/updates WinUI visual baseline.
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33688.cs Adds UI test for BackButtonBehavior with CollectionView ItemsSource change.
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33458.cs Adds UI test for safe-area behavior with ControlTemplate/ContentPresenter.
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33352.cs Adds (currently commented-out) UI test draft for MacCatalyst exit crash scenario.
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33324.cs Adds UI test for CollectionView.EmptyView remeasure on layout changes.
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33171.cs Adds Windows UI test for title bar caption button responsiveness.
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue22058.cs Adds Windows/MacCatalyst UI test for system components following app theme.
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue20772.cs Adds Android UI test for pan/resize flicker regression.
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue17823.cs Adds Android UI test for CollectionView reordering with header.
src/Controls/tests/TestCases.HostApp/Issues/XFIssue/Issue6878.cs Removes a top-tab addition in an XF issue repro.
src/Controls/tests/TestCases.HostApp/Issues/XFIssue/HeaderFooterShellFlyout.cs Enables horizontal flyout footer orientation.
src/Controls/tests/TestCases.HostApp/Issues/Issue33688.cs Adds HostApp repro Shell/pages for BackButtonBehavior regression.
src/Controls/tests/TestCases.HostApp/Issues/Issue33458.cs Adds HostApp repro page for safe-area/ControlTemplate scenario.
src/Controls/tests/TestCases.HostApp/Issues/Issue33352.cs Adds HostApp repro page for MacCatalyst exit/theme crash investigation.
src/Controls/tests/TestCases.HostApp/Issues/Issue33324.cs Adds HostApp repro page for EmptyView remeasure issue (Android-focused).
src/Controls/tests/TestCases.HostApp/Issues/Issue33171.cs Adds HostApp repro page for Windows title bar visibility/caption buttons.
src/Controls/tests/TestCases.HostApp/Issues/Issue22058.cs Adds HostApp repro page for Windows title bar theme behavior.
src/Controls/tests/TestCases.HostApp/Issues/Issue20772.cs Adds HostApp repro page for Android pan/resize flicker behavior.
src/Controls/tests/TestCases.HostApp/Issues/Issue17823.xaml.cs Adds HostApp XAML code-behind for reorder-with-header repro.
src/Controls/tests/TestCases.HostApp/Issues/Issue17823.xaml Adds HostApp XAML UI for reorder-with-header repro.
src/Controls/tests/SourceGen.UnitTests/Maui33532Tests.cs Adds source-gen unit tests validating NaN emission as double.NaN.
src/Controls/tests/SourceGen.UnitTests/InitializeComponent/BindablePropertyHeuristic.cs Adds test covering Style Setter + heuristic BP resolution for source-generated BP patterns.
src/Controls/tests/Core.UnitTests/WebViewHelperTests.cs Expands tests to match new JS escaping behavior (slashes/newlines/separators).
src/Controls/tests/Core.UnitTests/ShellTests.cs Adds tests for duplicate sibling route validation and reuse scenarios.
src/Controls/tests/Core.Design.UnitTests/FontSizeDesignTypeConverterTests.cs Adds design-time converter tests for font size standard values behavior.
src/Controls/tests/Core.Design.UnitTests/Controls.Core.Design.UnitTests.csproj Includes new FontSizeDesignTypeConverterTests file.
src/Controls/src/Xaml/Properties/AssemblyInfo.cs Removes InternalsVisibleTo entries for CommunityToolkit assemblies.
src/Controls/src/SourceGen/SetterValueProvider.cs Adds fallback heuristic BP resolution for Setter generation.
src/Controls/src/SourceGen/NodeSGExtensions.cs Refactors target type lookup into shared helper used by source-gen.
src/Controls/src/SourceGen/GeneratorHelpers.cs Formats NaN/Infinity float/double as double.NaN/etc in generated code.
src/Controls/src/Core/ShellToolbar.cs Uses “effective” BackButtonBehavior lookup (fallback to Shell).
src/Controls/src/Core/Shell/Shell.cs Introduces GetEffectiveBackButtonBehavior + uses it for back handling.
src/Controls/src/Core/Shell/BaseShellItem.cs Validates routes for duplicates before setting Routing.Route.
src/Controls/src/Core/Routing.cs Adds sibling duplicate route validation helper.
src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt Records removal of ShellSectionRootRenderer.TraitCollectionDidChange override.
src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt Records removal of ShellSectionRootRenderer.TraitCollectionDidChange override.
src/Controls/src/Core/Properties/AssemblyInfo.cs Removes InternalsVisibleTo entries for CommunityToolkit assemblies.
src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.Android.cs Ensures touch handling sets e.Handled based on OnTouchEvent result.
src/Controls/src/Core/Platform/Android/InnerGestureListener.cs Switches to RawX/RawY for gesture deltas (reduces coordinate drift).
src/Controls/src/Core/Platform/AlertManager/AlertManager.iOS.cs Uses iOS/macOS multi-range callback for MaxLength on newer OS versions.
src/Controls/src/Core/Internals/PropertyPropagationExtensions.cs Stops propagating BackButtonBehaviorProperty via property propagation.
src/Controls/src/Core/Handlers/Items/ItemsViewHandler.Android.cs Forces EmptyView layout update when RecyclerView size changes.
src/Controls/src/Core/Handlers/Items/Android/Adapters/ReorderableItemsViewAdapter.cs Fixes reorder indices when a header is present.
src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellSectionRootRenderer.cs Removes TraitCollectionDidChange override (avoids teardown crash).
src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellSectionRenderer.cs Uses effective BackButtonBehavior lookup when intercepting back navigation.
src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellPageRendererTracker.cs Uses effective BackButtonBehavior lookup when syncing nav items.
src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellFlyoutContentRenderer.cs Adjusts flyout footer frame for SafeAreaInsets.Bottom.
src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellToolbarTracker.cs Uses effective BackButtonBehavior lookup across toolbar/back logic.
src/Controls/src/Core/Application/Application.cs Adds Windows hooks for theme changes and window added/removed callbacks.
src/Controls/src/Core/Application/Application.Windows.cs Applies theme + title bar button colors across windows on Windows.
src/Controls/src/Core.Design/FontSizeDesignTypeConverter.cs Disables standard values to avoid IDE suggesting obsolete names.
src/BlazorWebView/tests/DeviceTests/Elements/BlazorWebViewTests.BackNavigation.cs Adds Android device tests verifying back handler lifecycle registration/cleanup.
src/BlazorWebView/src/Maui/PublicAPI/net-android/PublicAPI.Unshipped.txt Records BlazorWebViewHandler.ConnectHandler override.
src/BlazorWebView/src/Maui/Android/BlazorWebViewHandler.Android.cs Adds Android back handling (OnBackPressed + predictive back integration).
src/BlazorWebView/src/Maui/Android/BlazorAndroidWebView.cs Tracks whether Back navigation was handled in OnKeyDown.
.github/agent-pr-session/pr-33152.md Adds agent session notes (PR review record).
.github/agent-pr-session/pr-33127.md Adds agent session notes (PR review record).
.github/agent-pr-session/issue-33352.md Adds agent session notes (issue exploration record).

Comment on lines +41 to +42
await Task.Delay(1000); // Slight delay to apply the theme change

Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

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

Same as above: a fixed Task.Delay before VerifyScreenshot is prone to flakiness. Prefer VerifyScreenshot(retryTimeout: ...) or waiting on a concrete UI signal that the theme change has applied.

Copilot uses AI. Check for mistakes.
Comment on lines +804 to +808
/// Tests if the Windows maximize/restore button is accessible and responsive
/// </summary>
/// <param name="app">The Windows app instance</param>
/// <param name="clickButton">Whether to actually click the maximize button (default: false)</param>
/// <returns>True if the maximize/restore button is accessible and responsive</returns>
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

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

The XML doc for TapMaximizeButton doesn’t match the method signature/behavior: it mentions a clickButton parameter and a boolean return value, but the method is void and always clicks when found. Please update the doc (or adjust the signature) so it accurately reflects what the method does.

Copilot uses AI. Check for mistakes.
SelectionChangedCommand="{Binding SelectionChangedCommand}"
SelectionChangedCommandParameter="{Binding SelectedTags}"
SemanticProperties.Description="Tags Collection">
SelectionChangedCommandParameter="{Binding SelectedTags}">
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

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

Removing SemanticProperties.Description here looks like an accessibility regression for screen readers (the tag selector loses its spoken description). If this was removed intentionally, consider replacing it with an equivalent description elsewhere; otherwise please restore it.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,29 @@
#if IOS || ANDROID
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

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

This UITest is wrapped in #if IOS || ANDROID, but the issue/page is marked as iOS-only. Including Android here risks running the test on Android where the scenario may not apply (or may behave differently/flakily). Consider restricting this to iOS only (or updating the issue/page metadata if Android is also affected).

Copilot uses AI. Check for mistakes.
Comment on lines +24 to +25
await Task.Delay(1000); // Slight delay to apply the theme change
VerifyScreenshot(includeTitleBar: true);
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

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

Using a fixed Task.Delay before VerifyScreenshot is likely to introduce flakiness; the test infra already supports VerifyScreenshot(retryTimeout: ...) for animations/theme propagation. Consider removing the delay and using retryTimeout (and/or a specific WaitFor... condition) instead.

Copilot uses AI. Check for mistakes.
Comment on lines +43 to +47
internal void RemoveEvent<TDelegate>(string eventName, TDelegate action)
where TDelegate : Delegate
{
if (_mapper.TryGetValue(eventName, out var delegates) && delegates != null)
{
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

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

LifecycleEventService.RemoveEvent is internal, but it’s being called from the BlazorWebView project (different assembly). This won’t compile unless the method is made public (and added to PublicAPI) or the removal functionality is exposed via a public API (e.g., on ILifecycleEventService).

Copilot uses AI. Check for mistakes.
Comment on lines +154 to +162
// Clean up lifecycle event handler to prevent memory leaks
if (_onBackPressedHandler != null)
{
var lifecycleService = TryGetLifecycleEventService();
if (lifecycleService != null)
{
lifecycleService.RemoveEvent(nameof(AndroidLifecycle.OnBackPressed), _onBackPressedHandler);
_onBackPressedHandler = null;
}
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

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

This call uses LifecycleEventService.RemoveEvent, but that method is internal in the Core project. Since BlazorWebView is a different assembly, this should not compile. Either make RemoveEvent public (and update PublicAPI) or remove the dependency on the internal method (e.g., by extending ILifecycleEventService or tracking registrations differently).

Suggested change
// Clean up lifecycle event handler to prevent memory leaks
if (_onBackPressedHandler != null)
{
var lifecycleService = TryGetLifecycleEventService();
if (lifecycleService != null)
{
lifecycleService.RemoveEvent(nameof(AndroidLifecycle.OnBackPressed), _onBackPressedHandler);
_onBackPressedHandler = null;
}
if (_onBackPressedHandler != null)
{
_onBackPressedHandler = null;

Copilot uses AI. Check for mistakes.
Comment on lines +30 to 31
BackNavigationHandled = false;
return false;
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

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

For non-Back keys, this override currently resets BackNavigationHandled and returns false, which bypasses base.OnKeyDown and can break default key handling (e.g., keyboard navigation/shortcuts). Consider returning base.OnKeyDown(keyCode, e) when you don’t handle the event, while still resetting BackNavigationHandled appropriately.

Suggested change
BackNavigationHandled = false;
return false;
BackNavigationHandled = false;
return base.OnKeyDown(keyCode, e);

Copilot uses AI. Check for mistakes.
Comment on lines +43 to +45
#if WINDOWS // TimePicker pop up is only supported on Windows
App.Tap("TimePickerControl");
#endif
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

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

Inline #if WINDOWS inside the test method makes the test flow harder to follow and goes against the repo’s UI test pattern of hiding platform-specific behavior behind helper/extension methods. Consider moving the platform-specific tap into an App helper (or a test extension) so the test method stays platform-agnostic.

Copilot uses AI. Check for mistakes.
@PureWeen
Copy link
Member Author

PureWeen commented Feb 2, 2026

/rebase

Ahamed-Ali and others added 2 commits February 3, 2026 14:41
…dableProperty - Candidate Failure Feb 2nd (#33854)

### Root Cause of the issue



- The SourceGen XAML inflator was silently failing when a Setter
referenced a **non-BindableProperty**/ Property doesn't exist, while
XamlC and Runtime inflators correctly reported errors.
 
The Problem:
XamlC behavior (compile-time): Throws BuildException when encountering
<Setter Property="NonBindable" /> on a property that isn't a
BindableProperty
 
Runtime inflator behavior: Throws XamlParseException for the same
invalid XAML
 
SourceGen behavior (BEFORE fix):
 
SetterValueProvider.TryProvideValue() would detect the property can't be
resolved
Returns `false` without reporting any diagnostic

**Silently fails - no error message to the developer**
Test expected (`ShouldThrow(inflator: SourceGen`)
Assert.NotEmpty(result.Diagnostics) but got empty diagnostics ❌
Why It Failed Silently:
When TryGetBindablePropertyNameAndType() returns false (property not
found):


### Description of Change



- Detects failure: When TryGetBindablePropertyNameAndType returns false
(property doesn't exist or isn't a BindableProperty)
 
Reports diagnostic: Uses Descriptors.MemberResolution (MAUIX2002) - the
standard "cannot resolve member" error
 
Provides context:
 
Exact location in XAML file (line/column)
Property name that failed to resolve
Consistent behavior: Now all three inflators report errors for invalid
Setter properties:
 
✅ XamlC → BuildException
✅ Runtime → XamlParseException
✅ SourceGen → Diagnostic (MAUIX2002)


### Unit Test case failed

**ShouldThrow(inflator: SourceGen**

https://dev.azure.com/dnceng-public/public/_build/results?buildId=1272666&view=ms.vss-test-web.build-test-results-tab&runId=35509658&resultId=101501&paneView=debug

Test location:
https://github.com/dotnet/maui/blob/inflight/candidate/src/Controls/tests/Xaml.UnitTests/Validation/SetterOnNonBP.rt.xaml.cs#L22



### Issues Fixed



Fixes #33562 


### Screenshot



| Before Issue Fix | After Issue Fix |
|----------|----------|
| <img width="400" height="500"
src="https://github.com/user-attachments/assets/8128a742-460a-48fa-82bb-d310b80f688c"/>
| <img width="400" height="500"
src="https://github.com/user-attachments/assets/196f856b-9d45-4604-adc9-ae233ac09b1f">
|
<!-- 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

Enables XAML Source Generator (XSG) on the `Controls.ManualTests`
project by setting `MauiXamlInflator=SourceGen`.

## Changes

- Added `<MauiXamlInflator>SourceGen</MauiXamlInflator>` to enable XAML
Source Generator for better performance and debugging
- Added `NoWarn="0612"` for `HeaderFooterAddClearPage.xaml` which uses
deprecated `NamedSize` (`FontSize="Title"`)

## Testing

- Built and ran on MacCatalyst successfully
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.