Skip to content

Conversation

@PureWeen
Copy link
Member

@PureWeen PureWeen commented Jan 2, 2026

What's Coming

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

CollectionView

Docs

Editor

Image

Mediapicker

Navigation

Pages

RadioButton

SafeArea

ScrollView

Searchbar

Shell

Slider

Stepper

TabbedPage

Titlebar

Xaml

🔧 Infrastructure (1)
🧪 Testing (2)
📦 Other (3)
**Full Changelog**: https://github.com/dotnet/maui/compare/main...inflight/candidate

Copilot AI review requested due to automatic review settings January 2, 2026 23:35
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 is a January 5th candidate release containing multiple bug fixes and improvements across all platforms. The changes include:

  1. iOS/Apple Platform: Major refactoring of CALayer auto-sizing from NSObject-based KVO observer to Swift-based native framework, improvements to background image rendering, and keyboard scroll fixes
  2. Android: Drawable mutation fixes for SearchView, SafeArea edge detection improvements, ActivityForResult error logging, and Glide image loading optimizations
  3. Windows: Stepper value clamping fix, template test path adjustments, and package reference updates
  4. Cross-platform: ScrollView null content handling and XAML TemplateBinding ordering fixes

Reviewed changes

Copilot reviewed 107 out of 144 changed files in this pull request and generated no comments.

Show a summary per file
File Description
WindowsTemplateTest.cs Adjusts published app path construction for different .NET versions
MauiStepper.cs Adds min/max clamping to prevent invalid internal values
SearchViewExtensions.cs Fixes race conditions by mutating drawables before applying tints
SafeAreaExtensions.cs Adds detection for views extending beyond screen during transitions
ViewExtensions.cs Changes iOS background images from pattern to CALayer-based rendering
CALayerAutosizeObserver.cs Deleted - Replaced by Swift implementation
MauiCALayerAutosizeToSuperLayerBehavior New Swift-based framework for CALayer auto-sizing
ScrollViewHandler (Android/Windows) Improves null content handling
ActivityForResultRequest.android.cs Adds diagnostic trace logging for unregistered requests
PlatformInterop.java Adds size constraints to Glide image loading
Maui31939.xaml New XAML unit test for CommandParameter TemplateBinding ordering
Various test files New UI tests for Shell icon colors, Stepper clamping, CollectionView scrolling
Files not reviewed (1)
  • src/Core/AppleNative/PlatformInterop/MauiPlatformInterop.xcodeproj/project.xcworkspace/contents.xcworkspacedata: Language not supported

@PureWeen
Copy link
Member Author

PureWeen commented Jan 3, 2026

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@sheiksyedm
Copy link
Contributor

@kubaflo The below test fails due to your PR changes. Can you look into this failure?

[iOS 26] Navigation hangs after rapidly open and closing new page using Navigation.PushAsync

image

@kubaflo
Copy link
Contributor

kubaflo commented Jan 6, 2026

@sheiksyedm #33380

@sheiksyedm
Copy link
Contributor

/azp run maui-pr-uitests 

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@PureWeen PureWeen force-pushed the inflight/candidate branch from 4d73f0a to 8eab1e5 Compare January 9, 2026 02:06
@PureWeen
Copy link
Member Author

PureWeen commented Jan 9, 2026

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@PureWeen
Copy link
Member Author

PureWeen commented Jan 9, 2026

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@sheiksyedm
Copy link
Contributor

@PureWeen There are two test failures that occurred continuously, which are not related to the candidate branch commits. These failures also occur on the main branch. We have added fixes for these flaky issues in a separate PR. Therefore, I confirm that it is fine to merge.
image

@PureWeen
Copy link
Member Author

/rebase

BagavathiPerumal and others added 5 commits January 13, 2026 10:31
…fter PushModalAsync with Task.Yield() (#32479)

<!-- 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 was caused by a timing inconsistency in Android’s modal
navigation behavior. When invoking PushModalAsync() with animated:
false, Android displays the modal fragment but returns control before
the modal is fully initialized and ready for interaction. Subsequently,
if Task.Yield() is followed by PopModalAsync(), the pop operation
attempts to interact with a modal that has not yet completed its loading
process, resulting in the application hanging.

This problem does not occur with animated modals, as the animation
duration provides sufficient time for the modal to complete its loading
sequence before any subsequent operations are executed.

### Fix Description:

The fix involves ensuring that non-animated modals are fully loaded
before allowing any subsequent operations. A new
event, PresentationCompleted, has been introduced to signal when Android
confirms that the modal is completely initialized and ready for use.
With this improvement, when PushModalAsync() is called with animated:
false, the method waits for the PresentationCompletedevent before
returning control. This ensures that the modal is ready for any
follow-up operations, such as Task.Yield() or PopModalAsync(). The
Animated modals continue to function as before to maintain optimal
performance.

### Issues Fixed
Fixes #32310

### 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/e1dae5fb-fd7d-4433-87b5-999c6a98cb10">|<video
width="100" height="100" alt="After Fix"
src="https://github.com/user-attachments/assets/5dfa902b-1f0f-41a1-b1c0-c3a0a56f439c">|
…Latest macOS Version (#33157)

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

### Issue Details
After updating to the latest macOS version, the system traffic light
button size and spacing increased, causing the TitleBar leading content
to overlap with the window controls.

### Description of Change

<!-- Enter description of the fix in this section -->
Updated the left margin in TitleBar.cs from 80 to 90 to provide enough
space for the enlarged traffic light buttons and prevent overlap.

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

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

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

| Before  | After  |
|---------|--------|
| **Mac**<br> <img
src="https://github.com/user-attachments/assets/3b692c45-896d-4674-8ec5-a68aab88ff3a"
width="600" height="300"> | **Mac**<br> <img
src="https://github.com/user-attachments/assets/9642dadf-1aed-422a-8deb-68e901e437e9"
width="600" height="300"> |

---------

Co-authored-by: Stephane Delcroix <stephane@delcroix.org>
…3071)

App crashes because of changing a shared Drawable on the fly. I found
out it is the SearchBar. It only happens on Android and in large apps
with lots of screens. Unfortunately I can't reproduce it in the
TestSuite. But by reading the docs of Android this crash is common and
caused by changing a Drawable which is still referenced. With a custom
SearchBarHandler the issues is resolved.

```Backtrace (top frames):
  #00 pc 00000000006b8694  /system/lib64/libhwui.so
      android::getRootAlpha(_JNIEnv*, _jobject*, long) +4

  #1 pc 0000000002256c90  /memfd:jit-cache (deleted)
      art_jni_trampoline +112

  #2 pc 000000000223bc4c  /memfd:jit-cache (deleted)
      android.graphics.drawable.VectorDrawable.-$$Nest$smnGetRootAlpha +108

  #3 pc 000000000223bb20  /memfd:jit-cache (deleted)
      android.graphics.drawable.VectorDrawable$VectorDrawableState.getAlpha +144

  #4 pc 00000000025c50e0  /memfd:jit-cache (deleted)
      android.graphics.drawable.VectorDrawable.getAlpha +128

  #5 pc 00000000025c4f9c  /memfd:jit-cache (deleted)
      android.graphics.drawable.VectorDrawable.getOpacity +124

  #6 pc 00000000025c1ea8  /memfd:jit-cache (deleted)
      android.widget.ImageView.isOpaque +152

  #7 pc 000000000227979c  /memfd:jit-cache (deleted)
      android.view.View.invalidateInternal +428

  #8 pc 00000000025c4790  /memfd:jit-cache (deleted)
      android.widget.ImageView.invalidateDrawable +256

  #9 pc 000000000224419c  /memfd:jit-cache (deleted)
      android.graphics.drawable.Drawable.invalidateSelf +156

  #10 pc 000000000260e710  /memfd:jit-cache (deleted)
      android.graphics.drawable.VectorDrawable.setTintList +192

  #11 pc 00000000025d0094  /memfd:jit-cache (deleted)
      **android.graphics.drawable.Drawable.setTint +148**
```

### Description of Change

- Changes tinting of Androids SearchBar to unified setTint instead of
setColorFilter
-  Mutates the drawable before setting the tint.

### Issues Fixed
Issue is fixed with a custom handler for now.

Fixes #33070
### Root Cause
On Windows, `TabbedPage` uses WinUI `Frame` navigation to display each
tab’s content. Each tab’s platform view (native UI element) is hosted
inside a WinUI `Page` through a `ContentPresenter`.
During rapid tab switching, the platform view is reassigned to a new
WinUI `Page` while still attached to the previous one. WinUI does not
allow a UI element to exist in two visual trees simultaneously, which
causes the crash.
 
### Description of Change
Added a `_displayedPage` tracking field to maintain the correct
displayed MAUI Page during navigation, allowing `NavigateToPage` to skip
early if the requested page is already displayed and avoid redundant
navigation. The method also now clears the previous WinUI Page’s
`ContentPresenter` to explicitly detach the platform view and prevent
the “element already has a parent” WinUI error. In
`UpdateCurrentPageContent`, a skip guard avoids reassigning content that
is already set, while `_displayedPage` is updated only after successful
content assignment. Finally, OnHandlerDisconnected resets
`_displayedPage` to null to ensure proper cleanup and prevent stale
references.

### Issues Fixed
Fixes #32824 
 
Tested the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Output Video
| Before Issue Fix | After Issue Fix |
|------------------|-----------------|
| <img width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/4ae17a81-a399-4cd6-856d-ca4938cb683b"
/> | <img width="350" alt="withfix"
src="https://github.com/user-attachments/assets/5927a164-22d8-45bc-a910-003bfbc1927a"
/> |
###  Description of Change

#### This PR reopens the work from the closed PR
[#28210](#28210)
This pull request introduces multiple updates to the `Issue18193` test
cases. The main changes focus on renaming button variables and their
`AutomationId` properties to enhance clarity and consistency, along with
minor refactoring aimed at resolving reliability issues on Catalyst
platforms within CI environments. Although the specific cause of the
ongoing CI failures has not been conclusively identified, these
modifications tackle frequent issues that can impact UI test reliability
on Catalyst platforms.

### Test updates:

Removed the `#if TEST_FAILS_ON_CATALYST` directive and the related
comment from the `Issue18193` test file.
Updated the test steps in the `ShellNavigationShouldWorkInMoreTab`
method to use the new `AutomationId` values for button interactions.

<img width="366" height="289" alt="Screenshot 2025-09-17 at 6 29 36 PM"
src="https://github.com/user-attachments/assets/000226c7-16b8-4547-8c6b-64d76f32c8fb"
/>

### Issues Fixed

Fixes #27206
prakashKannanSf3972 and others added 21 commits January 13, 2026 10:31
…in Shell (#27580)

## Issue: The color of the custom FlyoutIcon in Shell resets to the
default blue instead of retaining its original color.

### RootCause

By default, `UIImageRenderingMode` is set to `Automatic`, allowing the
rendering behavior to be determined based on the UI context. When a
custom `FlyoutIcon` is applied, it does not retain its original color
but instead adapts to the predefined tinting behavior, leading to
unintended color changes.

### Description of Change

The image rendering mode is now set to
`UIImageRenderingMode.AlwaysOriginal`, ensuring that custom icons
maintain their original colors without being altered by default
rendering behavior.

- When no custom `FlyoutIcon` is set, its color can still be modified
using `Shell.ForegroundColor`.
- When a custom `FlyoutIcon` is applied, it now preserves its original
image color without automatic tinting.
- If color customization for the custom icon is needed,
`Shell.ForegroundColor` should be set accordingly to allow the color
modification to be applied.

### Issues Fixed

Fixes #6738 

**Tested the behaviour in the following platforms**

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

### Output 

|Before|After|
|--|--|
|<img
src="https://github.com/user-attachments/assets/cf86c574-6c7a-4426-a40d-39032395fe2e">|<img
src="https://github.com/user-attachments/assets/c647c915-8db5-4c41-918f-223bde1d8dfd">|

---------

Co-authored-by: SyedAbdulAzeem <syedabdulazeem.a@syncfusion.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](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

This PR ensures that the `Value` property of `Slider` and `Stepper`
controls is correctly preserved regardless of the order in which
`Minimum`, `Maximum`, and `Value` properties are set (either
programmatically or via XAML bindings).

## Problem

When using XAML data binding, the order in which properties are applied
depends on XAML attribute order and binding evaluation timing. The
previous implementation would clamp `Value` immediately when `Minimum`
or `Maximum` changed, using the current (potentially default) range.
This caused:

- `Value=50` with `Min=10, Max=100` would get clamped to `1` (default
max) if `Value` was set before `Maximum`
- The user's intended value was lost and could never be restored

## Solution

The fix introduces three private fields:
- `_requestedValue`: stores the user's intended value before clamping
- `_userSetValue`: tracks if the user explicitly set `Value` (vs.
automatic recoercion)
- `_isRecoercing`: prevents `_requestedValue` corruption during
recoercion

When `Minimum` or `Maximum` changes:
1. If the user explicitly set `Value`, restore `_requestedValue`
(clamped to new range)
2. If not, just clamp the current value to the new range

This allows `Value` to "spring back" to the user's intended value when
the range expands to include it.

## Issues Fixed

- Fixes #32903 - Slider Binding Initialization Order Causes Incorrect
Value Assignment in XAML
- Fixes #14472 - Slider is very broken, Value is a mess when setting
Minimum
- Fixes #18910 - Slider is buggy depending on order of properties
- Fixes #12243 - Stepper Value is incorrectly clamped to default min/max
when using bindableproperties in MVVM pattern
- Closes #32907
-
## Testing

Added comprehensive unit tests for both `Slider` and `Stepper`:
- All 6 permutations of setting Min, Max, Value in different orders
- Tests for `_requestedValue` preservation across multiple range changes
- Tests for value clamping when only range changes (user didn't set
Value)

**Test Results:** 98 tests passed (39 Slider + 59 Stepper)

## Breaking Changes

**Behavioral change in event ordering:** The order of `PropertyChanged`
events for `Stepper` may change in edge cases where `Minimum`/`Maximum`
changes trigger a `Value` change. Previously, `Value` changed before
`Min`/`Max`; now it changes after. This is an implementation detail and
should not affect correctly-written code.
# Conflicts:
#	src/Controls/tests/Core.UnitTests/StepperUnitTests.cs
### Description of Change

Clamping value to minimum and maximum in the MauiStepper for Windows
implementation.

### Issues Fixed

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

### Description of Change

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

This PR just adds a log telling users why a task was cancelled

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

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

---------

Co-authored-by: Pedro Jesus <pedrojesus@Pedros-MacBook-Pro.local>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…eAreaEdges="Container" in .NET MAUI (#33285)

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

### Description of Change

<!-- Enter description of the fix in this section -->
This pull request adds new test cases and platform-specific logic to
improve the handling and validation of SafeAreaEdges in .NET MAUI apps,
particularly on Android. The changes address reported issues where UI
elements were overlapped by system UI (like the status bar), or where
SafeAreaEdges behavior was inconsistent during navigation and tab
switching. Additionally, a platform fix is included to handle view
layout transitions more reliably.

**New test cases for SafeAreaEdges issues:**

* Added `Issue32941`, `Issue33034`, and `Issue33038` test pages and
corresponding UI tests to validate correct SafeAreaEdges behavior during
navigation, on multiple tabs, and after navigation transitions. These
tests are Android-specific and skipped on unsupported platforms.
[[1]](diffhunk://#diff-a9913175b99e229959d1848e065c5a4276458d14b093ab51367f836f24c60772R1-R84)
[[2]](diffhunk://#diff-88878b4873fe994a3e3f9aaafb7b4185b6c5375c436e6b5494c1769ffc59f503R1-R55)
[[3]](diffhunk://#diff-ced7ebe30769719552ea4f7284a5a4edeb8574b0172eec9fdacba5500e1bc052R1-R48)
[[4]](diffhunk://#diff-6eef3a4e7c3630ed5c7f9777bfd0cd566c333f09428c2826ad1f71b983658800R1-R39)
[[5]](diffhunk://#diff-d4ce09076d608bf0a3a3cf8cf98ed98a3441fec9c09d89ae0728462c12454aa3R1-R32)
[[6]](diffhunk://#diff-7d2378e3aeaf582726a213e2eff17dedcfe843fc86e92ea3db73c89b89598c53R1-R26)

**Android SafeAreaInsets handling improvement:**

* Updated `SafeAreaExtensions.cs` to detect when a view is still being
positioned (e.g., during Shell fragment transitions) and proactively
request insets to be reapplied after layout settles, preventing children
from processing invalid data and reducing layout glitches.

### 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 #33034
Fixes #32941
Fixes #33038

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

On a recent `macios` workload, a regression caused issues with
`WeakReference`s bringing lots of crashes in our app, all tied to
`KVO`s.

It potentially causes an issue with hot-reload which may or may not be
related.
```
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'Microsoft.Maui.Platform.StaticCAShapeLayer'.
   at ObjCRuntime.ThrowHelper.ThrowObjectDisposedException(Object o) in /Users/builder/azdo/_work/2/s/macios/src/ObjCRuntime/ThrowHelper.cs:line 52
   at Foundation.NSObject.get_SuperHandle() in /Users/builder/azdo/_work/2/s/macios/src/Foundation/NSObject2.cs:line 660
   at CoreAnimation.CALayer.RemoveFromSuperLayer() in /Users/builder/azdo/_work/2/s/macios/src/build/dotnet/ios/generated-sources/CoreAnimation/CALayer.g.cs:line 783
   at Microsoft.Maui.Platform.StaticCAShapeLayer.RemoveFromSuperLayer()
   at Microsoft.Maui.Platform.ContentView.RemoveContentMask()
   at Microsoft.Maui.Platform.ContentView.WillRemoveSubview(UIView uiview)
   at Foundation.NSObject.ReleaseManagedRef() in /Users/builder/azdo/_work/2/s/macios/src/Foundation/NSObject2.cs:line 458
   at Foundation.NSObject.NSObject_Disposer.Drain(NSObject ctx) in /Users/builder/azdo/_work/2/s/macios/src/Foundation/NSObject2.cs:line 1072
```

Given we're never unsubscribing from the KVO legacy observer, what we're
doing may lead to issues.

This PR introduces an `.xcframework` for Apple platforms which could
really help in the future also for other purposes.

I moved the observer to a `Swift` implementation which relies on the new
KVO API which lets you skip the unsubscribe and all those managed
weak-refs.

### Security

For security concerns, the MAUI team should use the attached script to
re-build the `.xcframework.zip` and commit that on my behalf like we did
with Android in the past.

<img width="759" height="62" alt="image"
src="https://github.com/user-attachments/assets/bd372451-9e39-4a24-9d59-b0dbdadd5258"
/>

This is how the project looks like:
<img width="410" height="406" alt="image"
src="https://github.com/user-attachments/assets/7be12553-40ec-4afc-a88e-3109c5c0eb2e"
/>

---------

Co-authored-by: Rolf Bjarne Kvinge <rolf@xamarin.com>
…33195)

### Issue details
On iOS, Shell.NavBarIsVisible does not update correctly when switching
between ShellContent. If the navigation bar is hidden on one page, it
can remain hidden on the next page even when it should be visible.

### Root cause
NavBar visibility was not updated when the page changed. On Android, it
was handled on page changed, but iOS did not handle it.

### Description of change
NavBar visibility is now updated whenever the page changes, ensuring the
correct visibility state is applied. While addressing this, an
additional issue was identified where the navigation bar title briefly
showed the previous page’s title when switching ShellContent. This
happened because the current page was being set after the navigation
animation completed. The fix now sets the current page before the
animation starts, ensuring both NavBar visibility and title are updated
correctly during ShellContent transitions.

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

Resaving UpdateSearchHandlerMenuItemForTabNavigation test images, since
previously the titles (CatsPage and DogsPage) were not centered
correctly and the selection indicator was not fully visible. With this
fix, both the title alignment and the selection indicator are now
updated properly.

### Issues Fixed

Fixes #33191

### Screenshots

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/d41fadf2-2cb1-4f16-8cda-ae284078d0c6">
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/8898360a-8f73-4739-a945-9997aae3f53c">)
|
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Description of Change

To make CV2 handlers the default, set cv2handlers to true. 

(i.e) when we use **CollectionView** / **CarouselView** = >
`CollectionViewHandler2` and `CarouselViewHandler2` are used by default.

Explicitly setting CollectionView1/CarouselView1 or
CollectionView2/CarouselView2 will configure the corresponding handlers
correctly, as before.
This pull request improves the inline documentation for several core UI
controls in the codebase by replacing XML documentation includes with
explicit XML doc comments. These changes enhance the clarity and
accessibility of API documentation directly in the source files, making
it easier for developers to understand the purpose and usage of
properties, events, and methods without relying on external XML files.

The most important changes are grouped below by control:

**CheckBox:**
- Replaced `<include>` tags with detailed XML doc comments for the
class, properties (such as `IsChecked`, `Color`), and events (like
`CheckedChanged`), providing clear summaries and usage notes.
[[1]](diffhunk://#diff-bd2ec4da02a6675bb7819ddf37cf1fe855f2cecf756165776f14e682570b1392L10-R30)
[[2]](diffhunk://#diff-bd2ec4da02a6675bb7819ddf37cf1fe855f2cecf756165776f14e682570b1392L63-R97)
[[3]](diffhunk://#diff-bd2ec4da02a6675bb7819ddf37cf1fe855f2cecf756165776f14e682570b1392R142-R144)

**Editor:**
- Added explicit XML doc comments for bindable properties
(`CharacterSpacingProperty`, `AutoSize`, `HorizontalTextAlignment`,
`VerticalTextAlignment`) and the `Completed` event, clarifying their
behavior and default values.
[[1]](diffhunk://#diff-e1e01bd8d7674e0d2b75effc62926da199a7dd860ddf89326477c2ea061dff15L32-R32)
[[2]](diffhunk://#diff-e1e01bd8d7674e0d2b75effc62926da199a7dd860ddf89326477c2ea061dff15L62-R83)
[[3]](diffhunk://#diff-e1e01bd8d7674e0d2b75effc62926da199a7dd860ddf89326477c2ea061dff15R97-R103)

**ImageButton:**
- Replaced `<include>` tags with comprehensive XML doc comments for the
class, all bindable properties, events (`Clicked`, `Pressed`,
`Released`), and internal methods, providing detailed descriptions,
remarks, and default values.
[[1]](diffhunk://#diff-efc9658e08fe3b783f24e1b9270bdaff4208083a016aad6990d025937841c2adL13-R185)
[[2]](diffhunk://#diff-efc9658e08fe3b783f24e1b9270bdaff4208083a016aad6990d025937841c2adL173-R304)

**RadioButton:**
- Added explicit XML doc comments for the class and its constants,
describing their purpose and usage in grouping and visual states.

These updates ensure that developers have immediate access to up-to-date
documentation within the code, improving maintainability and developer
experience.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Shane Neuville <shneuvil@microsoft.com>
# Conflicts:
#	src/Controls/src/Core/ImageButton/ImageButton.cs

# Conflicts:
#	src/Controls/src/Core/SearchBar/SearchBar.cs
### Root Cause of the issue

- The `CollectionViewUpdated` method in CarouselViewController2 is not
called when the ItemsSource is updated from another page, because
CollectionViewUpdated is null at the time of invocation. When navigating
away from the page, the event handler is unsubscribed, leaving it null.
As a result, the replaced items were not reflected.



### Description of Change



- When the ItemsSource is updated on another page and navigate back to
the page containing the CarouselView, refresh the currently visible
items in AttachingToWindow so they are properly updated.


### Issues Fixed



Fixes #31148 



### Tested the behaviour in the following platforms



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



### Screenshot



| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/956a5bad-2064-46c5-8ae7-1f6dde3c85d4">
| <video
src="https://github.com/user-attachments/assets/eac1d3c5-69d6-45ad-81c7-a745d5b4c581">
|

---------

Co-authored-by: Matthew Leibowitz <mattleibow@live.com>
This pull request updates several project files to improve Windows
platform support and modernize dependencies. The main changes involve
updating Windows SDK package versions, adding the
`Microsoft.WindowsAppSDK` package to relevant projects, and making
adjustments for publishing and output handling.

Fixes #30858

Attempt 1 #30665
Attempt 2 #31281

**Dependency updates:**

* Updated `MicrosoftWindowsAppSDKPackageVersion` to `1.8.251003001` and
`MicrosoftWindowsSDKBuildToolsPackageVersion` to `10.0.26100.4654` in
`eng/Versions.props`, ensuring projects use the latest Windows SDKs.

**Project file improvements for Windows support:**

* Added `Microsoft.WindowsAppSDK` as a `PackageReference` to
`Essentials.csproj`, `Graphics.Skia.csproj`, `Graphics.Win2D.csproj`,
and duplicated in `Graphics.csproj` to ensure consistent Windows App SDK
usage across graphics and essentials projects.
[[1]](diffhunk://#diff-f243c2b1e6b28c505c27e07d7cb7a99764386669ce229c6b856c32ca67faaf00R42)
[[2]](diffhunk://#diff-f23bffcd581d332998a68c42c65149fa447d2d3bed3d3c0ebf458e279f51e8dfR37)
[[3]](diffhunk://#diff-dc41b78aa310aeed937c387045a62fb5f2ae3ce0ce3bb304a7c21782d30c25a6R30)
[[4]](diffhunk://#diff-008ec03ba4c24598765341193edb331fec925e36d0f68e4d1bcbbea940790f9dR43)
* Removed Windows-specific property settings from
`Controls.Xaml.csproj`, simplifying project configuration for Windows
builds.

**Build and publishing process adjustments:**

* Added new MSBuild targets (`GetTypeScriptOutputForPublishing`,
`GetTypeScriptCopyToOutputDirectoryItems`) in `Directory.Build.targets`
to improve TypeScript output handling during publishing.
* Updated asset path logic in `WindowsTemplateTest.cs` to better handle
runtime identifier (RID) directories when publishing packaged Windows
apps.

---------

Co-authored-by: MartyIX <203266+MartyIX@users.noreply.github.com>
Co-authored-by: Shane Neuville <shneuvil@microsoft.com>
### What
Prevents a re-entrant/feedback-loop scenario during CanExecute
evaluation where forcing dependency bindings to apply (e.g.,
CommandParameter) can recursively trigger further CanExecute refreshes
and lead to hangs.

### Why
GetCanExecute currently forces binding application for dependent
properties on every evaluation. In scenarios involving frequent command
refresh (e.g., MultiBinding-driven CommandParameter updates), this can
cause repeated binding reapplication and re-entrant CanExecute calls.

### How
Only force dependency binding application when it appears pending:
- dependency is bound
- dependency value is currently null

This keeps the original dependency ordering intent while avoiding
unnecessary re-application.

### Tests
- dotnet test
./src/Controls/tests/Xaml.UnitTests/Controls.Xaml.UnitTests.csproj
- dotnet test
./src/Controls/tests/Xaml.UnitTests/Controls.Xaml.UnitTests.csproj
--blame-hang --blame-hang-timeout 10s --filter
FullyQualifiedName~Maui18123

---------

Co-authored-by: Shane Neuville <shneuvil@microsoft.com>
…ng Navigation.PushAsync - fix (#32456)

Added additional null checks for page and renderer references in
ShellSectionRenderer to prevent potential null reference exceptions
during navigation and view controller handling.

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

### Description of Change

Add null checks in ShellSectionRenderer
Added additional null checks for page and renderer references in
ShellSectionRenderer to prevent potential null reference exceptions
during navigation and view controller handling.

|Before|After|
|--|--|
|<video
src="https://github.com/user-attachments/assets/d63c59c1-8559-4d10-87d1-f1c8b67f8ea8"
width="300px"></video>|<video
src="https://github.com/user-attachments/assets/b5b6cf6c-29fb-4953-a9d7-f1f30988a3dc"
width="300px"></video>|

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

<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Issue Details
ContentPage background images display incorrectly on iOS by tiling in a
repeating pattern instead of showing a single scaled image.

### Root Cause
The iOS implementation used a pattern color API that creates tiled
patterns without scaling options. This tiles the image at original size
rather than scaling it to fill the view.


### Description of Change
Replaced the pattern color approach with a scalable layer that stretches
the image to fill view bounds. This matches Android's scaling behavior
and follows MAUI's standard layer management pattern used for gradient
backgrounds.

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

### Test case

Test case Issue17789 is already included in the source.

### Output  ScreenShot

| Before  | After  |
|---------|--------|
| <img width="354" height="735" alt="BeforeFix"
src="https://github.com/user-attachments/assets/8520b49b-617c-46e5-a29a-3a9b26e5b0c0"
/> | <img width="354" height="735" alt="AfterFix"
src="https://github.com/user-attachments/assets/402a8975-4d2b-4e2f-a362-ae22bcedec56"
/> |
…ction View (#33343)

# Fix #33264 - RadioButtonGroup not working with CollectionView

Fixes #33264

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

Fixed `RadioButtonGroup.SelectedValue` binding not working when
RadioButtons are inside a CollectionView's ItemTemplate while
RadioButtonGroup attached properties are set on a parent layout outside
the CollectionView.

**Quick verification:**
- ✅ Tested on Android - Issue resolved, all tests passing
- ✅ Tested on iOS - Issue resolved (user verified)
- ✅ Edge cases tested
- ✅ UI tests added and passing

## Root Cause

RadioButtonGroupController only registered RadioButtons through
`ChildAdded` events. When RadioButtons were dynamically created inside a
CollectionView's ItemTemplate, they never triggered `ChildAdded` events
on the parent layout where `RadioButtonGroup.GroupName` and
`RadioButtonGroup.SelectedValue` were set.

Without registration, when a RadioButton was checked,
`GetGroupController()` returned null, so
`HandleRadioButtonGroupSelectionChanged()` was never called and the
`SelectedValue` binding was never updated.

## Solution

Enhanced RadioButton to actively search up the visual tree for a
matching RadioButtonGroup controller when checked, rather than relying
solely on event-based registration:

**Key Changes:**

1. **`RadioButton.OnGroupSelectionChanged()`** - If no controller
registered, searches ancestors for matching group and registers
dynamically

2. **`RadioButton.FindControllerInAncestors()`** - Walks up visual tree
to find layout with matching `RadioButtonGroup.GroupName`

3. **`RadioButtonGroupController.RegisterRadioButton()`** - Public
method to register RadioButton with controller

4. **`RadioButtonGroup.GetController()`** - Exposes controller access
for RadioButton

5. **`RadioButtonGroupController.SetSelectedValue()`** and
**`SetGroupName()`** - Enhanced to proactively register discovered
RadioButtons

**Files Changed:**
- `src/Controls/src/Core/RadioButton/RadioButton.cs` - Added ancestor
search logic (+33 lines)
- `src/Controls/src/Core/RadioButton/RadioButtonGroupController.cs` -
Added dynamic registration (+55 lines)
- `src/Controls/src/Core/RadioButton/RadioButtonGroup.cs` - Exposed
controller access (+5 lines)

## Testing

**Before fix (Android):**
- Initial SelectedValue: '' 
- After tapping 'Choice 2', SelectedValue: '' ❌

**After fix (Android):**
- Initial SelectedValue: 'None' 
- After tapping 'Choice 2', SelectedValue: 'Choice 2' ✅ 
- After tapping 'Choice 3', SelectedValue: 'Choice 3' ✅
- Test Run Successful. Total tests: 1  Passed: 1

**After fix (iOS):**
- User verified - working correctly ✅

**Edge Cases Tested:**
- ✅ RadioButtons in CollectionView DataTemplate - Primary scenario, now
working
- ✅ Multiple radio button selections - Sequential taps update binding
correctly
- ✅ Binding updates in both directions - Property changes verified

**Platforms Tested:**
- ✅ Android - All tests passing
- ✅ iOS - User verified working

## Test Coverage

- ✅ Test page:
`src/Controls/tests/TestCases.HostApp/Issues/Issue33264.xaml`
- ✅ Code-behind:
`src/Controls/tests/TestCases.HostApp/Issues/Issue33264.xaml.cs`
- ✅ NUnit test:
`src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33264.cs`
- ✅ Tests exact scenario from issue report

## Breaking Changes

None - the fix adds proactive discovery without changing existing
behavior for scenarios that already work.
)

## Summary

Fix SafeArea inset handling when SoftInputMode is set to AdjustPan or
AdjustNothing on Android.

## Problem

When SoftInputMode is set to AdjustPan, the MAUI framework was
incorrectly modifying padding when the keyboard appeared. With
AdjustPan, Android handles keyboard visibility by panning the window, so
MAUI should not apply any additional padding adjustments.

## Solution

### SafeAreaExtensions.cs Fix
- Use `SoftInput.MaskAdjust` to properly detect AdjustPan mode
(distinguishes from AdjustNothing)
- When AdjustPan is detected, consume insets and return immediately
without modifying padding
- This allows Android's native AdjustPan behavior to work correctly

### Test Updates
- Updated 9 Issue28986 SafeArea test files to explicitly set
`SoftInput.AdjustNothing` for consistent test behavior
- Added Issue32041AdjustPan test to validate AdjustPan mode behavior
- Added Issue33276 test to validate safe area padding restoration after
keyboard closes

## Files Changed
- `src/Core/src/Platform/Android/SafeAreaExtensions.cs` - Core fix for
AdjustPan detection
- 9 Issue28986 test files - Set SoftInput.AdjustNothing mode
- Issue32041AdjustPan test page and UI test - New test for AdjustPan
validation
- Issue33276 test page and UI test - New test for padding restoration
validation

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



<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>

> Create a new pr from this pr #33145
but only include the changes and tests related to adjustpan and
adjustnone. Don't include anything related to adjustresize


</details>



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

💬 We'd love your input! Share your thoughts on Copilot coding agent in
our [2 minute survey](https://gh.io/copilot-coding-agent-survey).

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com>
Co-authored-by: Shane Neuville <shneuvil@microsoft.com>
…r MinimumValue - Candidate PR test failure fix- 33363 (#33392)

### Root Cause of the issue



- `Stepper_SetIncrementAndVerifyValueChange` and
`Stepper_SetIncrementValue_VerifyIncrement` in the candidate failed
because the previous test,
Stepper_ResetToInitialState_VerifyDefaultValues, updated the Minimum
value to 10.

- When the next test (Stepper_SetIncrementAndVerifyValueChange) runs, a
new ViewModel is created and the default values (Value = 0, Minimum = 0)
are set in StepperFeature. However, MapValue is called first during the
time, the Minimum value still retains the value 10 from the previous
test. Although MAUI correctly updates PlatformStepper.Value, the native
UIStepper automatically clamps the value based on the old Minimum value,
causing the test to fail.

### Description of Change



- Before updating `platformStepper.Value`, the code first checks if
MinimumValue needs updating and applies it. This ensures iOS always
clamps against the current/correct MinimumValue, not a stale one.

#### Example Scenario

Old state: Min=5, Value=5
New state: Min=0, Value=2
Without fix: If Value is set first (to 2), iOS sees Min=5 (stale) and
clamps Value back to 5
With fix: Min is updated to 0 first, then Value is set to 2 successfully


### Regressed PR 

#32939

### Issues Fixed



Fixes #



### Tested the behaviour in the following platforms



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



### Screenshot



| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/0ddeba45-0110-4362-96b3-ed8404fe83a1">
| <video
src="https://github.com/user-attachments/assets/8cc43af4-b7c5-4f1d-a943-a9f476286069">
|

---------

Co-authored-by: Shane Neuville <shneuvil@microsoft.com>
…ge width exceeds height (#33413)

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

Reverts the changes from #33045 which introduced a `constrainSize`
parameter to Glide image loading methods.

## Changes

### PlatformInterop.java
- Removed `constrainSize` parameter overloads from `prepare()`,
`loadInto()`, and `load()` methods
- Removed `.override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)`
constraint logic
- Reverted all image loading methods (`loadImageFromFile`,
`loadImageFromUri`, `loadImageFromStream`) to original signatures

### Deleted Test Files
- `TestCases.HostApp/Issues/Issue32869.cs`
- `TestCases.Shared.Tests/Tests/Issues/Issue32869.cs`
- `TestCases.HostApp/Resources/Raw/Issue32869.png`
- Android/iOS snapshot files for Issue32869

> [!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:
>
> - `plugins.gradle.org`
> - Triggering command: `/usr/lib/jvm/temurin-17-jdk-amd64/bin/java
/usr/lib/jvm/temurin-17-jdk-amd64/bin/java
--add-opens=java.base/java.lang=ALL-UNNAMED
--add-opens=java.base/java.lang.invoke=ALL-UNNAMED
--add-opens=java.base/java.util=ALL-UNNAMED
--add-opens=java.prefs/java.util.prefs=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
--add-opens=java.base/java.util=ALL-UNNAMED
--add-opens=java.prefs/java.util.prefs=ALL-UNNAMED
--add-opens=java.base/java.nio.charset=ALL-UNNAMED
--add-opens=java.base/java.net=ALL-UNNAMED
--add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED
--add-opens=java.xml/javax.xml.namespace=ALL-UNNAMED -Xmx2048m
-Dfile.encoding=UTF-8 -Duser.country -Duser.language=en -Duser.variant
-cp
/home/REDACTED/.gradle/wrapper/dists/gradle-8.13-all/54h0s9kvb6g2sinako7ub77ku/gradle-8.13/lib/gradle-daemon-main-8.13.jar`
(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/dotnet/maui/settings/copilot/coding_agent)
(admins only)
>
> </details>

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



<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>

> Can you revert this PR #33045


</details>



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

✨ Let Copilot coding agent [set things up for
you](https://github.com/dotnet/maui/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com>
…e - 1 (#33384)

This pull request refines the logic for setting the search icon color in
the Android `SearchView`. This PR
#33071 set the search icon color to
transparent if no color was specified, which caused the search icon to
become invisible and led to search bar-related test failures. Now, if no
custom search icon color is provided, the icon will use the platform's
default primary text color instead of becoming transparent.

**Android SearchView icon color handling:**

* Updated `UpdateSearchIconColor` in `SearchViewExtensions.cs` to apply
the default primary text color (`TextColorPrimary`) to the search icon
when no custom color is set, instead of making it transparent.

<table>
<tr>
<td>
Before fix
</td>
<td>
After fix
</td>
</tr>
<tr>
<td>




https://github.com/user-attachments/assets/22c5dc6f-2e8a-417d-89da-afaa422c9e15
</td>
<td>



https://github.com/user-attachments/assets/b4289eb2-7266-48a2-be12-eb0eabecb40f
</td>
</tr>
</table>
…33393)

This pull request updates UI test cases by reverting Shell navigation
test changes that continue to fail in Mac CI.

- ShellNavigationShouldWorkInMoreTab test case was previously failing in
CI on the Mac platform but was passing locally. Therefore, this PR
#31653 was created to resolve the
issue. However, the ShellNavigationShouldWorkInMoreTab test still fails
in CI on the Mac platform even after the changes. So, the changes from
#31653 were reverted.
…ts (#33380)

### Description of Change

Fixes long-press back button navigation not triggering `OnAppearing` and
other navigation events in Shell.

**Problem:** Test expected `OnAppearing count: 2`, got `OnAppearing
count: 1`

**Root cause:** PR #29825 replaced `SendPop()` with manual stack
synchronization (`SyncStackDownTo()`), which doesn't trigger navigation
events.

**Fix:** Simplified `DidPopItem` to use stack-sync detection:
- Stacks in sync → Shell already handled pop → return early  
- Stacks out of sync → user-initiated (long-press) → call `SendPop()`

**Key insight:** Tab tap updates Shell's stack BEFORE `DidPopItem` is
called, but iOS long-press pops directly without notifying Shell first.

**Regression chain:**
| PR | What happened |
|-----|---------------|
| #24003 | Fixed #23892 with `_popRequested` flag |
| #29825 | Removed flag, added `SyncStackDownTo()` - **broke
long-press** |
| #32456 | Added null checks, maintained broken state |
| #33380 | **This PR** - simplified fix using stack-sync detection |

**Removed:** `SyncStackDownTo()` method (44 lines)  
**What to avoid:** Don't remove stack count comparison - distinguishes
user vs programmatic navigation.

### Issues Fixed

Fixes #33379

**Related:** #23892, #29798 (verified not regressed ✅)

---------

Co-authored-by: Shane Neuville <shneuvil@microsoft.com>
@PureWeen
Copy link
Member Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@PureWeen
Copy link
Member Author

The UITests being reported on github doesn't match up with latest commit
https://dev.azure.com/dnceng-public/public/_build/results?buildId=1251806&view=results is green for the latest commit of a626440

@PureWeen PureWeen merged commit cfdbcef into main Jan 13, 2026
163 of 172 checks passed
@PureWeen PureWeen deleted the inflight/candidate branch January 13, 2026 23:17
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.

RadioButtonGroup not working with CollectionView