Skip to content

Comments

January 19th, Candidate#33574

Merged
PureWeen merged 16 commits intomainfrom
inflight/candidate
Jan 25, 2026
Merged

January 19th, Candidate#33574
PureWeen merged 16 commits intomainfrom
inflight/candidate

Conversation

@PureWeen
Copy link
Member

@PureWeen PureWeen commented Jan 16, 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 16 commits with various improvements, bug fixes, and enhancements.

Checkbox

CollectionView

🔧 Fixes

Essentials

Image

Label

Mediapicker

Navigation

Picker

Shell

Templates

Xaml

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

Copilot AI review requested due to automatic review settings January 16, 2026 17:53
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 release candidate pull request dated "January 19th, Candidate" containing multiple bug fixes, accessibility improvements, test additions, and code formatting changes. The PR addresses several issues across different areas of the .NET MAUI framework including UI testing infrastructure, template accessibility, platform handlers, and navigation.

Changes:

  • Added comprehensive UI test infrastructure improvements with new helper methods and test cases for Shell, Picker, CollectionView, and Label
  • Enhanced accessibility in MAUI mobile template with improved semantic properties and screen reader announcements for picker controls
  • Fixed critical platform-specific bugs including Android checkbox theming, Windows toolbar color clearing, Picker IsOpen state, and Label text measurement
  • Added source generator unit tests for indexer bindings and observable property support
  • Code formatting and whitespace cleanup across multiple XAML processing files

Reviewed changes

Copilot reviewed 65 out of 101 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/TestUtils/src/UITest.Appium/HelperExtensions.cs Added ClosePicker() helper for cross-platform picker dismissal
src/Templates/src/templates/maui-mobile/Pages/*.xaml Improved accessibility with better semantic descriptions for picker controls
src/Templates/src/templates/maui-mobile/PageModels/*.cs Added screen reader announcements for picker state changes
src/Templates/src/templates/maui-mobile/AppShell.xaml Added semantic properties to shell content navigation items
src/Graphics/src/Graphics/ColorUtils.cs Whitespace cleanup
src/Essentials/test/DeviceTests/Tests/FileSystem_Tests.cs Added tests for FileResult with file paths and multiple stream reads
src/Essentials/src/MediaPicker/MediaPicker.ios.cs Fixed FileResult creation to preserve FileName and ContentType
src/Essentials/src/FileSystem/FileSystem.windows.cs Fixed FileResult.OpenReadAsync to handle null File property
src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt Added LabelHandler.GetDesiredSize API entry
src/Core/src/Platform/Windows/MauiToolbar.xaml.cs Fixed toolbar foreground color clearing when null
src/Core/src/Platform/Android/CheckBoxExtensions.cs Fixed Material 3 checkbox theming with cached default tints
src/Core/src/Handlers/Picker/PickerHandler.Android.cs Fixed IsOpen state synchronization on dialog dismiss
src/Core/src/Handlers/Label/LabelHandler.Android.cs Fixed multi-line label width measurement for non-Fill alignment
src/Core/AndroidNative/maui/.../MauiCustomTarget.java Added context destruction checks before Glide operations
src/Controls/tests/Xaml.UnitTests/Controls.Xaml.UnitTests.csproj Added MAUIG2045 to warnings suppressions
src/Controls/tests/TestCases..Tests/snapshots//*.png Added screenshot baselines for ShellColorsResetOnNavigation test
src/Controls/tests/TestCases.Shared.Tests/UtilExtensions.cs Added TapFirstSearchResult helper for SearchHandler testing
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/*.cs Added UI tests for Issues 33356, 33331, 33227, 33158, 32932, 31782
src/Controls/tests/TestCases.HostApp/Issues/*.cs Added test pages for the corresponding issue tests
src/Controls/tests/SourceGen.UnitTests/InitializeComponent/IndexerBindings.cs Added comprehensive indexer binding tests
src/Controls/tests/SourceGen.UnitTests/BindingDiagnosticsTests.cs Added diagnostic verification tests
src/Controls/tests/Core.UnitTests/ShellNavigatingTests.cs Added test for RemovePage disconnecting handlers in Shell
src/Controls/tests/Core.UnitTests/NavigationUnitTest.cs Added tests for RemovePage disconnecting handlers
src/Controls/tests/BindingSourceGen.UnitTests/ObservablePropertyTests.cs Added tests for CommunityToolkit.Mvvm ObservableProperty support
src/Controls/src/Xaml/*.cs Code formatting and whitespace cleanup
Files not reviewed (1)
  • src/Controls/src/SourceGen/xlf/MauiGResources.Designer.cs: Language not supported

/// <param name="app">Represents the main gateway to interact with an app.</param>
/// <param name="x">Optional X coordinate for Windows tap. Default is 0.</param>
/// <param name="y">Optional Y coordinate for Windows tap. Default is 0.</param>
public static void ClosePicker(this IApp app, int windowsTapx = 0, int windowsTapy = 0)
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

Parameter names 'windowsTapx' and 'windowsTapy' have inconsistent casing. Should be 'windowsTapX' and 'windowsTapY' following PascalCase convention for parameter names, or rename to 'windowsX' and 'windowsY' for brevity.

Copilot uses AI. Check for mistakes.
Comment on lines +89 to +95
else if (app is AppiumWindowsApp)
{
if (windowsTapx != 0 || windowsTapy != 0)
{
app.TapCoordinates(windowsTapx, windowsTapy);
}
}
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

Windows platform does nothing when coordinates are (0, 0). This creates inconsistent behavior - the method should either always tap a default location on Windows (like 'Cancel' button) or document why coordinates are required. Consider adding a default tap action or throwing an exception when coordinates are not provided.

Copilot uses AI. Check for mistakes.
OnPropertyChanged(nameof(HasCompletedTasks));
}

partial void OnIsCategoryPickerExpandedChanged(bool value)
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

Extra space between 'void' and 'OnIsCategoryPickerExpandedChanged' - should be single space.

Copilot uses AI. Check for mistakes.
Comment on lines +75 to +76
AColor tintColor2 = accent.ToPlatform();
return ColorStateListExtensions.CreateCheckBox(tintColor2);
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

Variable name 'tintColor2' is unclear. Should be renamed to 'accentTintColor' or 'fallbackTintColor' to better describe its purpose.

Copilot uses AI. Check for mistakes.
{
// Android does not support selecting elements in SearchHandler results
var y = searchHandler.GetRect().Y + searchHandler.GetRect().Height;
app.TapCoordinates(searchHandler.GetRect().X + 10, y + 10);
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

Magic numbers 10 used for coordinate offsets without explanation. Consider adding constants like 'DefaultTapOffset = 10' with documentation explaining why this offset is needed.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,30 @@
#if TEST_FAILS_ON_WINDOWS // Existing PR for windows - https://github.com/dotnet/maui/pull/26728
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

Comment references PR #26728 for Windows failure, but the test is entirely excluded with preprocessor directive. If there's a Windows-specific fix pending, consider structuring the test to skip only Windows assertions rather than excluding the entire test file from compilation.

Copilot uses AI. Check for mistakes.

// For arrays, the handler should use empty string for indexer name (no property to listen to on the array itself)
// The array itself can't notify about element changes - only the containing property can
Assert.Contains("new(static source => source, \"Names\")", generated, StringComparison.Ordinal);
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

The test comment on line 310-311 says 'handler should use empty string for indexer name' but the assertion checks for 'Names' property handler. This appears contradictory - either the comment or the assertion may be incorrect.

Copilot uses AI. Check for mistakes.
@sheiksyedm
Copy link
Contributor

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@PureWeen PureWeen modified the milestones: .NET 10.0 SR4, .NET 10 SR5 Jan 21, 2026
PureWeen pushed a commit that referenced this pull request Jan 23, 2026
…e - 1 (#33602)

This PR addresses the UI test image failures that occurred in the
inflight/candidate branch #33574 and
includes updates to improve rendering and test stability across
platforms.

- Resaved snapshots for these test cases due to this PR fix
#33281: CanvasShouldHonorBlur,
VerifyScrollViewWithScrollToPositionCenterAndGridContent,
VerifyScrollViewWithRTLAndGridContent,
VerifyScrollViewWithScrollToPositionEndAndGridContent,
VerifyScrollViewWithScrollToPositionMakeVisibleAndGridContent,
VerifyScrollViewWithScrollToPositionStartAndGridContent,
DownSizeImageAppearProperly, Issue30440ImageShouldClipCorrectly,
IndicatorViewWithTemplatedIcon, VerifyCarouselLayoutOrientationChange,
VerifyCarouselViewItemsSourceClearedDynamically,
EmptyViewShouldDisplayWhenCollectionViewIsInsideVerticalStackLayout.
- Issue18751Test - Added the failing condition for Android due to the
image not loading on CI. Already restricted for other platforms; now it
fails on Android as well.
- Issue18751Test - Added the failing condition for Windows due to
AutomationId not working on layout in Appium.
- VariousSpanGesturePermutation - Increased the tap coordinates due to
this PR fix #33281 changes.

---------

Co-authored-by: sheiksyedm <sheiksyedm@syncfusion.com>
@sheiksyedm
Copy link
Contributor

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@PureWeen PureWeen modified the milestones: .NET 10 SR5, .NET 10.0 SR4 Jan 23, 2026
…s misalignment (#33281)

### Root Cause
On Android, for `Label` controls with `LineBreakMode="WordWrap"` and
multiple lines, `GetDesiredSize()` returns the full constraint width
instead of the actual rendered text width. This causes extra trailing
space and incorrect horizontal alignment when
`HorizontalLayoutAlignment` is set to `Start`, `Center`, or `End`.
Single-line and Fill alignment cases are unaffected.
 
### Description of Change
Updated `GetDesiredSize()` in `LabelHandler.Android.cs` to calculate the
actual content width for wrapped, multi-line labels with non-Fill
alignment. The implementation determines the widest rendered line using
`layout.GetLineWidth(i)` and uses that value (plus padding) as the
desired width.

### Issues Fixed
Fixes #31782 
Fixes #27614 
 
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/0eca49ce-3cfd-4f42-85cb-98560385a056"
/> | <img width="350" alt="withfix"
src="https://github.com/user-attachments/assets/a1cba4c6-d422-46ab-96ae-db0dc6dc0dc9"
/> |
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->
### Root Cause 
The load-time handling of the `IsEnabled` property for tab items was not
implemented on iOS. As a result, disabled tabs could still be selectable
and navigateable
### Description of Change
Updated `ShellItemRenderer.cs` to set the `IsEnabled` property of each
`TabBar` item based on the corresponding `IsEnabled` value during both
initial creation and when the items collection changes.
<!-- Enter description of the fix in this section -->

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

### Follow-up PR :  

- On **iOS 26** and **Catalyst 26**, navigation between tabs via drag
and selection gestures is handled separately in this PR
#33337.

### Tested the behavior in the following platforms

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

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/d133ccd3-abb1-44dd-9135-16b1ebeeb8e6">
| <video
src="https://github.com/user-attachments/assets/223f454c-fc1a-4167-b265-8ef6c7e0c8c6">
|
<!--
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
When the Picker dialog is closed using the cancel button or tapping
outside, the IsOpen property is not updated. Even though the Picker is
no longer visible, IsOpen stays true, causing the Picker state to be
incorrect.

### Description of Change
Updated the Android Picker handler to reset VirtualView.IsOpen to false
when the picker dialog is dismissed.

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

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

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

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

| Before  | After  |
|---------|--------|
| **Android**<br> <video
src="https://github.com/user-attachments/assets/5dc18c5f-a2d2-48cd-95eb-d150b210c4ce"
width="300" height="600"> | **Android**<br> <video
src="https://github.com/user-attachments/assets/c30f015d-5d2b-46cc-9bc1-d07ba9ed485c"
width="300" height="600"> |
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Description of Change

This pull request updates the way checkbox tint colors are handled on
Android, improving compatibility with both Material 2 and Material 3
themes. The main focus is on ensuring that the correct default or accent
color is used for checkbox foregrounds depending on the Material version
in use.

**Theme-aware checkbox tinting:**

* Introduced a static field `_defaultButtonTintList` in
`CheckBoxExtensions` to cache the default button tint for Material 3
themes, ensuring consistent appearance and avoiding unnecessary
recomputation.
* Updated the `GetColorStateList` method to:
- Use the default theme's button tint when Material 3 is enabled,
falling back to the cached `_defaultButtonTintList` if available.
- Continue using the accent color for Material 2 themes, preserving
existing behavior.

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

### Screenshots

Material Design Spec -
[CheckBox](https://m3.material.io/components/checkbox/specs)

| Material 2 | Material 3 |
|----------|----------|
| <img
src="https://github.com/user-attachments/assets/8bce9689-a698-49af-862f-24e56ec4f3cb">
| <img
src="https://github.com/user-attachments/assets/978b27eb-0e67-451c-8a3b-927434d6389a">
|

---------

Co-authored-by: Stephane Delcroix <stephane@delcroix.org>
…movePage() (#32289)

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

### Issue Details
When a non-visible page is removed from the navigation stack using
RemovePage(), its handler is not disconnected.

### Root Cause
The RemovePage() method removes the page from the navigation stack but
does not explicitly disconnect its handler.

### Description of Change
The handler is now properly disconnected when a page is removed using
RemovePage().

Regression PR: #24887

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

### Issues Fixed

Fixes #32239

### Screenshots

**Android:**
| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/890c3e4b-f520-4826-b942-6ec9e04233d1">
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/40ebc025-7298-4b43-8816-4932a01fb563">)
|

**iOS:**
| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/484e17cd-bd83-415e-af27-99acf893b203">
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/062a1c6d-047c-4bde-add2-d2d261763c87">)
|

---------

Co-authored-by: Stephane Delcroix <stephane@delcroix.org>
Co-authored-by: Rui Marinho <me@ruimarinho.net>
Co-authored-by: Shane Neuville <shneuvil@microsoft.com>
…ShellContent (#33228)

### Issue details
When switching between ShellContent items, navigation bar colors from
the previously displayed page are incorrectly applied to the next page,
even when the next page does not define any navigation bar colors.
On iOS, background and title colors persist across pages.
On Windows, the issue is limited to TitleColor, which remains applied
when navigating to an uncolored page.

### Root cause
iOS:
Navigation bar appearance is applied via SetAppearance in
ShellNavBarAppearanceTracker when colors are specified. However, when
navigating to a page without defined colors, the appearance is not
reset, causing previously applied colors to persist.

Windows:
The toolbar title foreground is updated only when a brush is provided.
When switching to a page without a TitleColor, the previous brush is not
cleared, so the title color remains.

### Description of change
iOS:
Reset the navigation bar appearance to the default native appearance
when no colors are specified, ensuring that colors from a previous page
are not carried over.

Windows:
Clear the toolbar title foreground when the brush is null, allowing the
title color to revert to the system default instead of retaining the
previous color.

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

### Issues Fixed

Fixes #33227

### Screenshots

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/0665c21a-f3b9-44e1-bb95-05678560ac73">
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/29758b20-8bb4-4393-8936-5b7ccd06aab8">)
|

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/3fd239fe-1b21-4ddb-8982-ed4939b47ab9">
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/f87c760e-3d24-4a53-b96c-1bf23b818482">)
|
…reated with full path (#28238)

### Issue details

Calling OpenReadAsync() on a FileResult constructed using the full path
constructor throws a NullReferenceException with the message: "Value
cannot be null. (Parameter 'windowsRuntimeFile')". This occurs because
the internal File property is null when a full path is provided.

### Description of Change

The changes fix the Exception in OpenReadAsync() by properly
initializing the File property when a FileResult is created with a full
path.

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

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

| Before  | After  |
|---------|--------|
| **Windows**<br> <img
src="https://github.com/user-attachments/assets/d0fd9a0f-7b7a-4c15-a15f-69f978060067"
> |**Windows**<br> <img
src="https://github.com/user-attachments/assets/0059d3d6-6350-487a-a8be-618cc6221b1e"
> |

---------

Co-authored-by: Shalini-Ashokan <102292178+Shalini-Ashokan@users.noreply.github.com>
…r Labels (#31619)

<!-- 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. !!!!!!!
-->
### Issue Description:
The Shell Flyout is implemented using a `UITableViewController` with a
`UITableView`, which iOS accessibility services announce as a "table".

### Description of Change:
Entirely hides the UITableView Accessibility and makes the
UIContainerCell to become a first responder, The inner UIContainerCell
cannot be individually detected — it is treated as a single grouped
element.

### Issues Fixed
Fixes #30894

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

### Output Screenshot
Before Issue Fix | After Issue Fix |
|----------|----------|
|<video width="300" height="150" alt="Before Fix"
src="https://github.com/user-attachments/assets/1862862a-ffee-4302-a46f-5ac083e39a0b">|<video
width="300" height="150" alt="After Fix" src
="https://github.com/user-attachments/assets/be969437-d5ea-4319-ac19-9b60bd0e1a68">|
…ced inside a VerticalStackLayout (#33134)

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

### Root Cause

- When the RecyclerView height is infinite, the EmptyView also receives
an infinite height constraint. During measurement, Int.MAX_VALUE is
assigned to represent this infinite height.
- However, while converting the RecyclerView’s infinite height to an
integer value, a pixel conversion issue occurs. As a result, the
EmptyView fails to render correctly and does not appear on the screen.

### Description of Change

- When the EmptyView height is infinite, the EmptyView is measured to
the exact infinite height when its height is set to Int.MAX_VALUE

Validated the behaviour in the following platforms
- [x] Android
- [x] Windows ,
- [x]  iOS, 
- [x] MacOS

### Issues Fixed

Fixes #32932

### Output

**Android**
|Before|After|
|--|--|
| <video
src="https://github.com/user-attachments/assets/e1bc87a9-cb07-4e08-86aa-f64159cdcd15"
>| <video
src="https://github.com/user-attachments/assets/1b89e70d-b93d-4c1f-9e0d-af9db32dbd7b">|

---------

Co-authored-by: Shane Neuville <shneuvil@microsoft.com>
Copilot AI and others added 7 commits January 23, 2026 16:53
- [x] Analyze the issue - understand TODOs in binding compilation logic
- [x] Identify files to modify: `CompiledBindingMarkup.cs`,
`KnownMarkups.cs`, `Descriptors.cs`, `MauiGResources.resx`, etc.
- [x] Build and test baseline (100 tests passing)
- [x] Add new diagnostic descriptors for binding-related errors
(matching XamlC error codes)
  - MAUIG2041: BindingIndexerNotClosed (matching XC0041)
  - MAUIG2042: BindingIndexerEmpty (matching XC0042)
  - MAUIG2043: BindingIndexerTypeUnsupported (matching XC0043)
  - MAUIG2045: BindingPropertyNotFound (matching XC0045)
- MAUIG2024: BindingWithXDataTypeFromOuterScope warning (matching
XC0024)
  - MAUIG2064: NamescopeDuplicate (matching XC0064)
- [x] Replace `return false; // TODO report diagnostic` with actual
diagnostic reporting
- [x] Replace `throw new Exception` with diagnostic reporting
- [x] Update resource strings to match XamlC messages
- [x] Add unit tests for the new diagnostics (6 tests)
- [x] Update AnalyzerReleases.Unshipped.md
- [x] Build and test (147 tests passing)
- [x] Run code review and address feedback
- [x] Run CodeQL checker (no security issues found)
- [x] Revert unrelated formatting changes
- [x] Fix alignment in Descriptors.cs
- [x] Change diagnostic prefix from MAUIX to MAUIG per reviewer feedback
- [x] Remove unreachable code in CompiledBindingMarkup.cs
- [x] Add missing test scenarios for MAUIG2024 and MAUIG2043 diagnostics
- [x] Support NoWarn metadata for source generator diagnostics
- [x] Add MAUIG2045 to NoWarn for test XAML files with intentional
binding errors
- [x] Address latest code review feedback:
- Refactored repeated indexer lookup pattern into reusable local
function
  - Removed localized message checks from diagnostic tests
- Fixed IndexerBindings test assertions to properly validate lambda
context using regex patterns that match actual generated code structure

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



<details>

<summary>Original prompt</summary>

> 
> ----
> 
> *This section details on the original issue you should resolve*
> 
> <issue_title>[XSG] Improve diagnostic reporting during binding
compilation</issue_title>
> <issue_description>We left several todos in the binding compilation
logic in the XAML source generator. We should try to match the warnings
and errors produced by XamlC, just with an adjusted error
code.</issue_description>
> 
> ## Comments on the Issue (you are @copilot in this section)
> 
> <comments>
> </comments>
> 


</details>

- Fixes #32904

<!-- 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: simonrozsival <374616+simonrozsival@users.noreply.github.com>
Co-authored-by: Simon Rozsival <simon@rozsival.com>
…blePropertyAttribute (#33028)

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

Binding source generators now support properties generated by
CommunityToolkit.Mvvm's `[ObservableProperty]` attribute. Previously,
bindings failed because MAUI generators cannot see properties generated
by other source generators.

**Implementation** (following PR #32954 pattern for RelayCommand):

- **BindingSourceGen/ITypeSymbolExtensions.cs**: Added
`TryGetObservablePropertyType()` to detect fields with
`[ObservableProperty]` and infer property types. Supports all three
documented field naming patterns: `camelCase`, `_camelCase`, and
`m_camelCase`. Includes validation for empty property names.

- **BindingSourceGen/PathParser.cs**: Enhanced `TryHandleSpecialCases()`
to handle ObservableProperty patterns as fallback when symbol resolution
fails.

- **BindingSourceGen/BindingSourceGenerator.cs**: Updated
`GetLambdaReturnType()` to infer types from ObservableProperty fields,
enabling C# lambda bindings.

- **SourceGen/ITypeSymbolExtensions.cs**: Updated `TryGetProperty()` to
check ObservableProperty-inferred properties, enabling XAML string-based
bindings.

- **Tests**: Added comprehensive unit tests in
`BindingSourceGen.UnitTests` (8 tests) to validate ObservableProperty
binding support across all field naming patterns and scenarios. Tests
verify the generated binding code by checking:
- Handler patterns: `new(static source => source, "PropertyName")` -
validates property path in generated code
- Setter expressions: `source.PropertyName = value;` - validates
property assignment

**Field Naming Pattern Support:**

All three CommunityToolkit.Mvvm documented naming conventions are
supported:
- `name` → `Name`
- `_name` → `Name`
- `m_name` → `Name`

**Works for both XAML and C# bindings:**

```csharp
public class MyViewModel
{
    [ObservableProperty]
    private string? name;  // Generates Name property
    
    [ObservableProperty]
    private ObservableCollection<Tag> _tags = new();  // Generates Tags property
    
    [ObservableProperty]
    private int m_count;  // Generates Count property
}
```

```xaml
<Label Text="{Binding Name}" />
<ListView ItemsSource="{Binding Tags}" />
```

```csharp
label.SetBinding(Label.TextProperty, static (MyViewModel vm) => vm.Name);
listView.SetBinding(ListView.ItemsSourceProperty, static (MyViewModel vm) => vm.Tags);
```

### Issues Fixed

Fixes #32597

<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>

> 
> ----
> 
> *This section details on the original issue you should resolve*
> 
> <issue_title>[XSG][BindingSourceGen] Add support for
CommunityToolkit.Mvvm ObservablePropertyAttribute source
generator</issue_title>
> <issue_description>Similar to #32597
> Related to #32953
> 
> The CommunityToolkit.Mvvm package contains a source generator which
generates bindable property bolierplate code based on the
`[ObservableProperty]` attribute:
https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/generators/observableproperty
> 
> Scenarios:
> ```c#
> // applied to a field
> [ObservableProperty]
> private string? name;
> 
> // generated code:
> /// <inheritdoc cref="_tags"/>
>
[global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator",
"8.3.0.0")]
> [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
> public
global::System.Collections.ObjectModel.ObservableCollection<global::TestSampleContentBindings.Models.Tag>
Tags
> {
>     get => _tags;
>     [global::System.Diagnostics.CodeAnalysis.MemberNotNull("_tags")]
>     set
>     {
> if
(!global::System.Collections.Generic.EqualityComparer<global::System.Collections.ObjectModel.ObservableCollection<global::TestSampleContentBindings.Models.Tag>>.Default.Equals(_tags,
value))
>         {
>             OnTagsChanging(value);
>             OnTagsChanging(default, value);
>
OnPropertyChanging(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangingArgs.Tags);
>             _tags = value;
>             OnTagsChanged(value);
>             OnTagsChanged(default, value);
>
OnPropertyChanged(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangedArgs.Tags);
>         }
>     }
> }
> ```
> 
> Our source generators cannot see properties generated by other source
generators, so the binding compilation will fail.
> 
> Our sample content template uses this source generator and we are
currently failing over to reflection-based bindings.</issue_description>
> 
> ## Comments on the Issue (you are @copilot in this section)
> 
> <comments>
> </comments>
> 


</details>



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

- Fixes #32955

<!-- 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: simonrozsival <374616+simonrozsival@users.noreply.github.com>
Co-authored-by: Simon Rozsival <simon@rozsival.com>
…n contentType property (#33390)

<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->
### Issue Details
The FileResult constructor was being called with (filePath, fileName)
but the second parameter expects a MIME type, not a filename. This
caused the filename to be stored as ContentType.

### Description of Change

<!-- Enter description of the fix in this section -->
Fixed FileResult initialization to properly preserve the filename and
ContentType.

### Regarding Test Case
Picking an image is not possible in a test.

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

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

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

| Before  | After  |
|---------|--------|
| **iOS**<br> <video
src="https://github.com/user-attachments/assets/47360519-a071-47eb-9a79-66069f8711a8"
width="300" height="600"> | **iOS**<br> <video
src="https://github.com/user-attachments/assets/47a43e9d-c90f-4c79-ac81-779e50198cff"
width="300" height="600"> |
…stroyed activities (#29780)

## Problem

Random crashes occurring on Android devices with the error:
```
java.lang.IllegalArgumentException: You cannot start a load for a destroyed activity
	at com.bumptech.glide.manager.RequestManagerRetriever.assertNotDestroyed(RequestManagerRetriever.java:236)
	at com.bumptech.glide.manager.RequestManagerRetriever.get(RequestManagerRetriever.java:110)
	at com.bumptech.glide.manager.RequestManagerRetriever.get(RequestManagerRetriever.java:92)
	at com.bumptech.glide.Glide.with(Glide.java:545)
	at com.microsoft.maui.glide.MauiCustomTarget.lambda$clear$0$com-microsoft-maui-glide-MauiCustomTarget(MauiCustomTarget.java:88)
```

This happens when Glide attempts to clear image targets using a Context
whose underlying Activity has been destroyed.

## Solution

Added defensive context destruction check in `MauiCustomTarget.clear()`
before calling `Glide.with(context).clear(this)`.

**Key Changes:**

1. **Added private context lifecycle validation methods to
MauiCustomTarget:**
- `isContextDestroyed()` - Checks if context/activity is destroyed or
finishing
- `getActivity()` - Safely extracts Activity from Context (handles
ContextWrapper chains)

2. **Protected MauiCustomTarget.clear() operation:**
- Added context check before calling `Glide.with(context).clear(this)`
- Includes verbose logging when the clear operation is skipped due to
destroyed context

**Behavior:**
- When context is destroyed, `clear()` returns early without attempting
to call Glide
- Matches Glide's own validation logic: `activity.isFinishing() ||
activity.isDestroyed()`
- Logs a debug message when clear is skipped (if verbose logging is
enabled)

**Example of the fix:**
```java
private void clear() {
    post(() -> {
        if (isContextDestroyed(context)) {
            if (logger.isVerboseLoggable) {
                logger.v("clear() skipped - context destroyed: " + resourceLogIdentifier);
            }
            return;
        }
        Glide
            .with(context)
            .clear(this);
    });
}
```

This is a surgical, minimal fix that targets the specific crash location
identified in the stack trace while maintaining all existing
functionality.

Fixes #29699.

---

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

<!-- 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: jfversluis <939291+jfversluis@users.noreply.github.com>
Co-authored-by: jonathanpeppers <840039+jonathanpeppers@users.noreply.github.com>
…33406)

<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->
### Root Cause : 
Navigation fails because `UISearchController` was dismissed before
`ItemSelected` was called, triggering a UIKit transition that
deactivates the Shell navigation context and prevents the navigation
from completing
### Description of Change :
Changed the order in `OnSearchItemSelected` in
`ShellPageRendererTracker.cs` to call `ItemSelected` before deactivating
the search controller for correct event handling.

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

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

### Tested the behavior in the following platforms

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

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/0e63dd86-1965-404a-8d07-6d3afd952498">
| <video
src="https://github.com/user-attachments/assets/af867272-434f-411e-9a6f-a68a87cfc3a7">
|
<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->

---------

Co-authored-by: Shane Neuville <shneuvil@microsoft.com>
### Issue Description:

VoiceOver does not read the ComboBox State correctly, In the sample, the
ComboBox behavior is implemented using SfTextInputLayout with a Picker.
However, I have already implemented the semantic properties for picker ,
it was overriden by SfTextInputLayout, the expectation is for VoiceOver
to recognise and announce it as a ComboBox state.

### Description of change :
Update SemanticProperties using property changed on IsOpen property in
picker to achieve the expected output.

> Note:
net9.0 PR - dotnet/maui-samples#651

### Issues Fixed
Fixes [#30899 ](#30899)

### Tested the behaviour in the following platforms
- [ ] Android
- [ ] Windows
- [ ] iOS
- [x] Mac
…e - 1 (#33602)

This PR addresses the UI test image failures that occurred in the
inflight/candidate branch #33574 and
includes updates to improve rendering and test stability across
platforms.

- Resaved snapshots for these test cases due to this PR fix
#33281: CanvasShouldHonorBlur,
VerifyScrollViewWithScrollToPositionCenterAndGridContent,
VerifyScrollViewWithRTLAndGridContent,
VerifyScrollViewWithScrollToPositionEndAndGridContent,
VerifyScrollViewWithScrollToPositionMakeVisibleAndGridContent,
VerifyScrollViewWithScrollToPositionStartAndGridContent,
DownSizeImageAppearProperly, Issue30440ImageShouldClipCorrectly,
IndicatorViewWithTemplatedIcon, VerifyCarouselLayoutOrientationChange,
VerifyCarouselViewItemsSourceClearedDynamically,
EmptyViewShouldDisplayWhenCollectionViewIsInsideVerticalStackLayout.
- Issue18751Test - Added the failing condition for Android due to the
image not loading on CI. Already restricted for other platforms; now it
fails on Android as well.
- Issue18751Test - Added the failing condition for Windows due to
AutomationId not working on layout in Appium.
- VariousSpanGesturePermutation - Increased the tap coordinates due to
this PR fix #33281 changes.

---------

Co-authored-by: sheiksyedm <sheiksyedm@syncfusion.com>
# Conflicts:
#	src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18751.cs
@PureWeen
Copy link
Member Author

/azp run maui-pr-uitests, maui-pr-devicetests

@azure-pipelines
Copy link

Azure Pipelines successfully started running 2 pipeline(s).

@PureWeen PureWeen enabled auto-merge January 25, 2026 19:32
@PureWeen PureWeen merged commit 61cb42a into main Jan 25, 2026
169 checks passed
@PureWeen PureWeen deleted the inflight/candidate branch January 25, 2026 19:42
@github-project-automation github-project-automation bot moved this from Todo to Done in MAUI SDK Ongoing Jan 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.