Skip to content

December 22nd, Candidate#33185

Merged
PureWeen merged 18 commits intomainfrom
inflight/candidate
Dec 29, 2025
Merged

December 22nd, Candidate#33185
PureWeen merged 18 commits intomainfrom
inflight/candidate

Conversation

@PureWeen
Copy link
Member

@PureWeen PureWeen commented Dec 16, 2025

CollectionView

Flyout

Flyoutpage

Mediapicker

Navigation

ScrollView

Searchbar

Shell

TitleView

Xaml

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

Copilot AI review requested due to automatic review settings December 16, 2025 21:07
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 December 22nd candidate release PR containing multiple bug fixes and test additions across the .NET MAUI codebase. The changes include fixes for stream disposal, SearchBar character spacing on Windows, iOS scroll view boundary handling, and several new UI and XAML unit tests.

  • Stream disposal fix to prevent double-dispose on Windows
  • SearchBar character spacing support for placeholder text on Windows
  • iOS ScrollView scroll offset clamping improvements
  • New XAML unit tests for CommandParameter template binding and IReadOnlyList.Count binding
  • New UI tests for SearchBar character spacing, CarouselView crash, TitleView disposal, FlyoutPage orientation, and Shell query attributes

Reviewed changes

Copilot reviewed 56 out of 75 changed files in this pull request and generated no comments.

Show a summary per file
File Description
ImageProcessor.shared.cs Prevents double disposal of streams when ApplyMetadataAsync returns the same stream
SearchBarExtensions.cs Implements character spacing for SearchBar placeholder text on Windows
ScrollViewHandler.iOS.cs Clamps scroll offsets to prevent negative values using Math.Clamp
Maui31939.xaml/.xaml.cs XAML unit test for CommandParameter TemplateBinding issue during reparenting
Maui13872.xaml/.xaml.cs XAML unit test for IReadOnlyList.Count compiled binding support
Issue30366.cs UI test for SearchBar CharacterSpacing property
Issue5669.cs Updated screenshot verification for iOS platform
Issue28557.cs UI test for CarouselView NRE fix (Windows-excluded)
Issue28201.cs UI test for TitleView disposal (Android-excluded)
Issue22719_1.cs UI test for FlyoutPage orientation handling (Android/iOS)
Issue22719.cs UI test for FlyoutPage window maximization (MacCatalyst/Windows)
Issue13537.cs UI test for Shell ApplyQueryAttributes
Bugzilla44461.cs Simplified ScrollView test to use screenshot verification
Various .png files New test screenshot snapshots for visual verification

@sheiksyedm
Copy link
Contributor

/azp run MAUI-UITests-public

@azure-pipelines
Copy link

No pipelines are associated with this pull request.

@sheiksyedm
Copy link
Contributor

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

sheiksyedm added a commit that referenced this pull request Dec 24, 2025
…mizingWindow test case images in PR 33185 - [12/22/2025] Candidate (#33271)

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

- Re-saved the ShouldFlyoutBeVisibleAfterMaximizingWindow images on Mac
and Windows platforms.

### Test cases:

- ShouldFlyoutBeVisibleAfterMaximizingWindow
@sheiksyedm
Copy link
Contributor

/rebase

@sheiksyedm
Copy link
Contributor

/rebase

Ahamed-Ali and others added 10 commits December 27, 2025 18:22
<!-- 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 of the issue



- Upon analysis, in iOS versions 18.4 and 18.0, GetCell is called when
PopAsync is invoked—navigating back to the MainPage (which contains the
CarouselView). At this point, _carouselViewLoopManager is properly set
through the Setup method, and a valid IndexPath is passed into GetCell,
resulting in correct updates.

- However, in iOS versions 15.5 and 16.0, GetCell is triggered
immediately when _viewModel.Source[0] is updated. At that time, the
CarouselViewLoopManager is still null, and since a valid index cannot be
retrieved, the else part of GetCell is executed with an invalid
IndexPath, leading to an ArgumentNullException.



### Description of Change



- To prevent ArgumentNullException caused by invalid IndexPath values
during the loop initialization phase, ensure that the
CarouselViewLoopManager is fully initialized before it is used. Once
initialized, it correctly returns a valid IndexPath using
FromRowSection, allowing the templated cell to be updated as expected in
all iOS versions.



### Issues Fixed



Fixes #28557 



### Tested the behaviour in the following platforms



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

### Tested Version

| iOS Version | App Crashed |
|----------|----------|
| 15.5 | Yes |
| 16.0 | Yes |
| 17.4 | No |
| 18.4 | No |


### Screenshot

### iOS 15.5

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/4df6973e-c658-4c89-a085-cc2035a593bf">
| <video
src="https://github.com/user-attachments/assets/25840d66-fa41-4a00-8e53-a262b405eca3">
|

### iOS 16.0

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/882829ed-fef4-40e9-a450-2972b4134c8e">
| <video
src="https://github.com/user-attachments/assets/4a5d0c48-e340-4b51-939e-6a6bf7518db7">
|

### iOS 17.4 && iOS 18.4


| iOS 17.4 | iOS 18.4 |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/5c167003-f5af-4989-87c7-d09b8d3b7b81">
| <video
src="https://github.com/user-attachments/assets/9c44bc1d-0956-4795-994b-2c4c314d40a7">
|
…yQueryAttributes(query) (#25663)

* Fix - 13573 fix changes

* Testcases commit

* Update Shell.cs

* commit for testcases

* commit for review changes

* Commit for class name changes

* Commit class name change

* Commit for review

* commit for testcase changes

* Commit for images

* Test case changes

* Update Issue13537.cs

* Update Issue13537.cs

* Update Issue13537.cs

* Update Shell.cs

* Update Shell.cs

* changes for initial triggering

* comments updated

* Update Issue13537.cs

* Update Issue13537.cs

commit testcase failure

* Changes for indentation

* Review changes

* Update Issue13537.cs
…tes (#33006)

Added unit tests to validate the fix for issues #13537 and #28453:

- TabBarNavigationSetsQueryAttributesProperty: Verifies QueryAttributesProperty is set when switching tabs
- TabBarNavigationWithGoToAsyncSetsQueryAttributesProperty: Verifies GoToAsync navigation sets property
- FlyoutItemNavigationSetsQueryAttributesProperty: Verifies FlyoutItem navigation triggers ApplyQueryAttributes
- NavigatingBackToTabSetsQueryAttributesProperty: Verifies navigating back to a tab sets property
- PopNavigationTriggersApplyQueryAttributes: Verifies pop navigation restores parameters
- ShellSectionChangedSetsQueryAttributesProperty: Verifies ShellSection changes trigger ApplyQueryAttributes

These tests ensure IQueryAttributable.ApplyQueryAttributes is called for all Shell navigation types.
…T>.Count (#32912)

* Fix binding to interface-inherited properties like IReadOnlyList<T>.Count

Fixes #13872

The runtime binding expression was not resolving properties inherited from parent interfaces. For example, IReadOnlyList<T>.Count would return null because Count is defined on IReadOnlyCollection<T>, not directly on IReadOnlyList<T>.

Added GetProperty() method that searches both base classes and implemented interfaces recursively, similar to how GetIndexer() already handles this case.

* Fix Maui32879Tests expected output after pragma warning merge
…32961)

When a Button inside a ControlTemplate has both Command and CommandParameter
with TemplateBinding, the async binding application path can cause Command
to be evaluated before CommandParameter resolves, resulting in CanExecute
being called with null parameter.

## Solution
Add a BindableProperty dependency mechanism via DependsOn() method. When
CommandProperty.DependsOn(CommandParameterProperty) is registered, the
CommandElement.GetCanExecute() forces the CommandParameter binding to apply
before calling CanExecute. This ensures the parameter value is available.

## Changes
- BindableProperty: Add Dependencies property and DependsOn() method
- BindableObject: Add ForceBindingApply() to force a binding to apply immediately
- CommandElement: Force dependency bindings to apply before calling CanExecute
- ButtonElement, CheckBox, SearchBar, MenuItem, RefreshView, TextCell: Register
  Command -> CommandParameter dependency
- All ICommandElement implementations: Pass CommandProperty to GetCanExecute()

## Testing
Added unit tests that verify:
1. Initial template binding works correctly
2. CommandParameter is preserved after reparenting (the bug scenario)
…ings (#32954)

* Initial plan

* Add RelayCommand support to binding source generators

Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>

* Consolidate RelayCommand detection logic into shared BindingSourceGen code

Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>

* Remove test files that cannot work in test environment

Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>

* Refactor RelayCommand logic into shared helper method

Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>

* Move RelayCommand logic to PathParser with special case handling

Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>

* Simplify TryGetProperty naming and add RelayCommand unit tests

Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>

* Enable expression-based bindings with RelayCommand support

Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>

* Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

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: Šimon Rozsíval <simon@rozsival.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Changed the condition for setting PrefersLargeTitles to enable large titles unless the display mode is set to Never, improving compatibility with different display modes.
)

### Issue Detail
When navigating using PushAsync and PopToRootAsync, the destructor was
not invoked when using PopToRootAsync.
 
### Root Cause
The TitleView was not properly disposed when using PopToRootAsync.
 
### Description of Change
Resolved the issue by disposing the TitleView using Disconnect, similar
to PopAsync.

Reference:
https://github.com/dotnet/maui/blob/main/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs#L345

### Issues Fixed

Fixes #28201

### Screenshots

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/23f571a4-f6f9-4978-b6d8-0a334b2dd593">
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/0c7e5202-bf49-4fbd-98b1-3028c1cbc8c8">)
|
…ceholder text (#30407)

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

The CharacterSpacing property in SearchBar behaves inconsistently across
platforms:

1) iOS/macOS: Not applied to search text or placeholder—both use default
spacing.
2) Windows: Applied to search text, but placeholder still shows default
spacing.

### Root Cause

**iOS**: The CharacterSpacing logic for SearchBar is defined in
UpdateCharacterSpacing() in TextFieldExtensions.cs, shared across Entry,
Editor, and SearchBar.

For Entry and Editor, it's triggered via MapFormatting(), which is
called from MapText() (e.g., in Entry.iOS), ensuring spacing is applied
on load and text change.
For SearchBar, MapFormatting() was not invoked, so CharacterSpacing
was never applied to either the search text or placeholder.

**Windows** - The CharacterSpacing property of the SearchBar is applied
only to the search text via the AutoSuggestBox.CharacterSpacing
property. However, the placeholder text is rendered by a separate
internal TextBlock that does not inherit this spacing, resulting in
default character spacing for the placeholder.

### Description of Change
**iOS**: The fix involves explicitly calling MapFormatting() within the
MapText() method of SearchBar.iOS.

**Windows**: The fix explicitly locates the TextBlock rendering the
placeholder using GetFirstDescendant<TextBlock>() and applies the same
CharacterSpacing to it within the OnLoaded lifecycle of the
AutoSuggestBox. This ensures that both search text and placeholder text
reflect the correct spacing consistently.

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

### Issues Fixed:
Fixes #30366 

### Screenshots

| | Before  | After |
|----------|---------|--------|
|PlaceHolder Text|  <img
src="https://github.com/user-attachments/assets/04e443ac-3931-4d2d-a51f-9947557cbb45">
|  <img
src="https://github.com/user-attachments/assets/63ab8cca-7e3e-40d3-b82d-2cc8f27f4965"> 
|
|SearchBar Text|  <img
src="https://github.com/user-attachments/assets/157a4b5a-c0e0-4424-9a0f-f2c9fea2432b">
|  <img
src="https://github.com/user-attachments/assets/dcecca30-081f-4ba7-bfda-000d2618fda3"> 
|
…lyst (#26825)

### Issue Details
When scrolling a ScrollView using the ScrollToAsync method with the
ScrollPosition.Center value, the item is incorrectly centered.

### Root Cause
The scroll offset values allow items to scroll into a negative position,
causing the item to be incorrectly centered.
 
### Description of Change
We clamp the scroll offset values to ensure the item does not scroll
into a negative position.

### 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 #26760 
Fixes #28965 

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

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

### Output Screenshot
| Before  | After  |
|---------|--------|
| <video
src="https://github.com/user-attachments/assets/be05f838-42bf-452c-bc1a-a34d02de006f"
width="320" height="240" controls></video> | <video
src="https://github.com/user-attachments/assets/02ca23f1-0d31-49c5-9862-767235845761"
width="320" height="240" controls></video> |

---------

Co-authored-by: Shalini-Ashokan <102292178+Shalini-Ashokan@users.noreply.github.com>
…n Mac Platform (#26701)

### Issue Details

- FlyoutPage.Flyout disappeared When the FlyoutPage is maximized

### Root Cause

- When the FlyoutPage is maximized, the flyout is removed even when
IsPresented is true. This causes the FlyoutPage's flyout to disappear.

### Description of Change

- When maximizing the Mac window, the FlyoutPage is removed in the
ViewWillTransitionToSize(CoreGraphics.CGSize toSize,
IUIViewControllerTransitionCoordinator coordinator) method using the
UpdatePresented(bool value) method. Here, there is no need to update the
FlyoutPage when maximizing the Mac window.
- Therefore, I have ignored the FlyoutPage update in this scenario.

### Issues Fixed
Fixes #22719

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

### Test Case:
This issue occurs only when resizing the Mac window, and we could not
find a way to automate the dynamic resizing of Mac windows. Therefore,
test cases for this scenario are not included in this PR.

### Output

|Before|After|
|--|--|
| <video
src="https://github.com/user-attachments/assets/079fceb7-02cd-430c-be9c-014838a1dc4f"
>| <video
src="https://github.com/user-attachments/assets/e13d7b26-5090-409b-aaf6-e375791854c2">|

---------

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

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

### Root cause

- When the ItemSizingStrategy is set to measure the first item, the
collection view’s grouped item header or footer template size is taken
from the first item’s size instead of the actual size of the grouped
item header or footer template.

### Description of changes

- I have ignored the first measured item’s size when applying it to the
grouped header or footer template, the collection view header or footer
view, and the collection view header or footer template in
PreferredLayoutAttributesFittingAttributes of TemplatedCell2.

### Issues Fixed

Fixes #33130 

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

### Output
**iOS**

|Before|After|
|--|--|
| <video
src="https://github.com/user-attachments/assets/deb143a4-5df0-463d-915c-16254bad658c"
>| <video
src="https://github.com/user-attachments/assets/56ba82de-f6d9-4b05-8ea7-2a12031282eb">|

**macOS**
|Before|After|
|--|--|
| <video
src="https://github.com/user-attachments/assets/094b3e91-8198-483f-8b87-f3f5777e48b4"
>| <video
src="https://github.com/user-attachments/assets/5937e5c3-feb5-4138-8c47-9f7a31095a16">|
@sheiksyedm
Copy link
Contributor

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@PureWeen
Copy link
Member Author

/rebase

@PureWeen PureWeen force-pushed the inflight/candidate branch 2 times, most recently from baab297 to 31a8f7b Compare December 29, 2025 17:10
PureWeen pushed a commit that referenced this pull request Dec 29, 2025
…se images in PR 33185 - [12/22/2025] Candidate (#33271)

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

- Re-saved the ShouldFlyoutBeVisibleAfterMaximizingWindow images on Mac and Windows platforms.

### Test cases:

- ShouldFlyoutBeVisibleAfterMaximizingWindow
#33257)

This pull request updates unit tests in the `Issues` test suite to use the `xUnit` testing framework instead of `NUnit`, modernizes test structure, and improves platform-specific screenshot verification. The most important changes are grouped below:

**Migration from NUnit to xUnit:**

* Replaced `NUnit` attributes and assertions with their `xUnit` equivalents in `Maui13872.xaml.cs` and `Maui31939.xaml.cs`, including changing `[TestFixture]` and `[Test]` to `[Collection("Issue")]`, `[Theory]`, and updating assertion methods. [[1]](diffhunk://#diff-4b69f656993fc5d70bff919b3e23b6516fed4319c75d9466dd2087502d0f5904L2-R27) [[2]](diffhunk://#diff-33c75e5cfbad2cc87eb4da8d7cdb72922dd439512e225be4931f5af08a3bb55eL9-R9) [[3]](diffhunk://#diff-33c75e5cfbad2cc87eb4da8d7cdb72922dd439512e225be4931f5af08a3bb55eL20-R54) [[4]](diffhunk://#diff-33c75e5cfbad2cc87eb4da8d7cdb72922dd439512e225be4931f5af08a3bb55eL67-R67) [[5]](diffhunk://#diff-33c75e5cfbad2cc87eb4da8d7cdb72922dd439512e225be4931f5af08a3bb55eL77-R77)

**Platform-specific Screenshot Verification:**

* Updated `ShouldFlyoutBeVisibleAfterMaximizingWindow()` to use platform-specific screenshot verification logic for MacCatalyst and Windows, ensuring correct UI validation across platforms.
…se images in PR 33185 - [12/22/2025] Candidate (#33271)

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

- Re-saved the ShouldFlyoutBeVisibleAfterMaximizingWindow images on Mac and Windows platforms.

### Test cases:

- ShouldFlyoutBeVisibleAfterMaximizingWindow
…e - 2 (#33299)

This pull request simplifies the `DatePickerControlPage.xaml.cs` code by removing the `ReinitializeDatePicker` method and its invocation. This streamlines the logic for navigating to the options page and reduces code duplication.

Code cleanup and simplification:

* Removed the `ReinitializeDatePicker` method, which handled manual re-creation and binding of the `DatePicker` control, as well as culture-specific date display updates. (`DatePickerControlPage.xaml.cs`)
* Removed the call to `ReinitializeDatePicker()` from the `NavigateToOptionsPage_Clicked` event handler, further simplifying the navigation logic. (`DatePickerControlPage.xaml.cs`)
…e - 3 (#33311)

This pull request adds a few lines to the `ShouldFlyoutBeVisibleAfterMaximizingWindow` test to improve the reliability of the test after entering full screen mode. The main change is to exit full screen and interact with the UI to ensure the test environment is reset.

* After verifying the screenshot in full screen mode, the test now exits full screen, waits for the "Label" element to appear, and taps it to ensure the UI is interactive and the flyout visibility can be properly tested.
@PureWeen
Copy link
Member Author

  • last failing test is flakey on main and will be fixed in a different PR

@PureWeen PureWeen merged commit 7b45118 into main Dec 29, 2025
158 of 161 checks passed
@PureWeen PureWeen deleted the inflight/candidate branch December 29, 2025 21:37
StephaneDelcroix pushed a commit that referenced this pull request Jan 5, 2026
…se images in PR 33185 - [12/22/2025] Candidate (#33271)

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

- Re-saved the ShouldFlyoutBeVisibleAfterMaximizingWindow images on Mac and Windows platforms.

### Test cases:

- ShouldFlyoutBeVisibleAfterMaximizingWindow
@github-actions github-actions bot locked and limited conversation to collaborators Jan 29, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CommandParameter TemplateBinding Lost During ControlTemplate Reparenting