Repository navigation
Conversation
Updated [Microsoft.AspNetCore.Authentication.Facebook](https://github.com/dotnet/dotnet) from 10.0.0 to 10.0.10. <details> <summary>Release notes</summary> _Sourced from [Microsoft.AspNetCore.Authentication.Facebook's releases](https://github.com/dotnet/dotnet/releases)._ No release notes found for this version range. Commits viewable in [compare view](https://github.com/dotnet/dotnet/commits). </details> Updated [Microsoft.AspNetCore.Authentication.Google](https://github.com/dotnet/dotnet) from 10.0.0 to 10.0.10. <details> <summary>Release notes</summary> _Sourced from [Microsoft.AspNetCore.Authentication.Google's releases](https://github.com/dotnet/dotnet/releases)._ No release notes found for this version range. Commits viewable in [compare view](https://github.com/dotnet/dotnet/commits). </details> Updated [Microsoft.AspNetCore.Authentication.MicrosoftAccount](https://github.com/dotnet/dotnet) from 10.0.0 to 10.0.10. <details> <summary>Release notes</summary> _Sourced from [Microsoft.AspNetCore.Authentication.MicrosoftAccount's releases](https://github.com/dotnet/dotnet/releases)._ No release notes found for this version range. Commits viewable in [compare view](https://github.com/dotnet/dotnet/commits). </details> Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
<!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Description of Change Removes the private `DropCompletedEventArgs.DropResult` property. The property was never assigned or consumed and always held its default value. `DropCompletedEventArgs` remains useful through its public `PlatformArgs` property. This does not change the public API surface. ### Issues Fixed Fixes #2839
…ating project cards (#37385) <!-- 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 The voice-over does not announce the project description when the focus moves to the border element within the item template of the CollectionView on the Mac platform. ### Root Cause SemanticProperties.Description was bound only to the project Name on the parent Border. Because the card is exposed as one accessible/selectable element, VoiceOver does not announce the child labels separately ### Description of Change Combined both Name and Description values into the Border semantic description. ### Issues Fixed Fixes #37142 **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | <video src="https://github.com/user-attachments/assets/20884ac2-7f4c-4907-8d97-02326a093be2" Width="600" Height="400"/>| <video src="https://github.com/user-attachments/assets/c0f63c4e-4e12-4af4-976d-439970db7a67" Width="600" Height="400"/> |
…ist item (#37340) <!-- 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 Issue Details When a VisualStateGroup is replaced through the VisualStateGroupList indexer, the existing implementation only updates the internal list: `visualStateGroups[index] = replacementGroup;` The replacement bypasses the lifecycle behavior used by Add, Insert, and Remove: * The old group remains subscribed to StatesChanged. * The replacement group is not subscribed to StatesChanged. * Group and state names are not revalidated. * State triggers are not updated for the replacement. * The associated VisualElement is not notified to reevaluate its visual state. ### Description of Change <!-- Enter description of the fix in this section --> * Updated the VisualStateGroupList indexer setter to correctly manage group replacement: * Reject null replacement values with ArgumentNullException. * Unsubscribe ValidateAndNotify from the replaced group. * Replace the group in the internal collection. * Subscribe ValidateAndNotify to the new group. * Explicitly call ValidateAndNotify(_internalList) after replacement. ### 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 #37171 <!-- 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> <img src="https://github.com/user-attachments/assets/1e6c5337-afcc-4e55-bba2-6852316fdf6a" width="300" height="600"> | **Android**<br> <img src="https://github.com/user-attachments/assets/006f5544-3393-4f3a-9774-86ff6d966947" width="300" height="600"> |
…me instead of item content in Narrator (#37421) <!-- 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 On Windows, `CollectionView`'s legacy handler (CV1), which is based on `ListView`, derives each item's screen reader name from the root element of the `DataTemplate`. When neither `AutomationProperties.Name` nor `SemanticProperties.Description` is set on that root element, WinUI falls back to calling `.ToString()` on the bound item. As a result, Narrator announces the internal type name: `Microsoft.Maui.Controls.Platform.ItemTemplateContext` instead of meaningful item content. This is native WinUI `ListView` behavior documented by Microsoft and is not specific to MAUI. ### Description of Change Set `SemanticProperties.Description` on the `DataTemplate` root, `TaskView`'s `Border`, and scope it to Windows only. This ensures Narrator announces the bound task title instead of the internal type name. Windows-only scoping is necessary because applying `SemanticProperties.Description` on iOS and Mac Catalyst causes the root element to become a single accessibility element, preventing VoiceOver from navigating to the inner `CheckBox`. ### Issues Fixed Fixes #36940 ### Platforms Tested - [x] iOS - [x] Android - [x] Windows - [x] Mac ### Screenshots | Before Fix | After Fix | |------------|-----------| | <video width="350" alt="withoutfix" src="https://github.com/user-attachments/assets/b35e24bc-0c59-4db1-8210-1be4fe5c2333" /> | <video width="350" alt="withfix" src="https://github.com/user-attachments/assets/89ad2456-5c9d-4060-8685-e108e9fe8c3e" /> |
<!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Description Fixes #29418. On Windows, `W2DGraphicsView` stored Win2D's callback-scoped `CanvasDrawingSession` on its persistent canvas. Win2D disposes that native session after the draw callback returns, but the stale managed reference remained available across repeated pointer-driven redraws and shutdown, leading to native access violations and heap corruption. This change clears the drawing session after canvas state has been reset. The nested cleanup guarantees the session and thread-local canvas owner are released even if state reset throws. @Kamalesh-Periyasamy, once the PR artifacts are available, could you please try them with your original application and let us know whether they resolve the crash? ### Tests - Added a Windows device test that performs an initial draw plus 100 explicit invalidation/draw cycles and verifies the drawing session is released after every callback. - Verified the test fails without the fix by observing the retained, already-disposed `CanvasDrawingSession`. - Core DeviceTests: 2,092 total, 1,981 passed, 111 skipped, 0 failed. - Ran the exact issue attachment twice for 120 seconds each with 3,848 presses and 38,480 pointer moves per run; both exited cleanly with code 0 and no correlated Windows application errors. - Also validated custom/default fonts, `ManipulationMode.All`/`None`, multiple views, redraw, resize, unload, and graceful shutdown. ### Video verification #### Before — original reported crash The issue author's original recording shows the attached app failing during pointer interaction: https://github.com/user-attachments/assets/eecd8e89-17c9-4764-b21e-9e6c15141fb4 #### After — fixed DLL under sustained pointer stress The exact attached application was rebuilt with an ABI-compatible fixed `Microsoft.Maui.Graphics.Win2D.WinUI.Desktop.dll`, then exercised with real `SendInput` pointer presses and moves for 120 seconds: https://github.com/user-attachments/assets/41a3e68c-e048-4d09-b677-aec1a9bc3af7 This recorded run delivered 11,622 presses and 116,220 pointer moves, then closed normally with exit code `0`. No correlated `Application Error` or `.NET Runtime` event was recorded. The native crash is intermittent: fresh recording attempts against the original DLL did not fail during the capture session, so the before clip above is the reporter's genuine original failure rather than a clean run being mislabeled or a crash being staged. The deterministic regression evidence is the baseline test retaining an already-disposed `CanvasDrawingSession`; the same test passes after this change. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 01dac3d5-7cea-4af6-ba68-fdc87f9ceb54
…ains prior ShellContent instances (#37390) <!-- Please keep the note below for people who 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 whether this change resolves your issue. Thank you! ### Description of Change **Memory management and event subscription improvements:** * Adds a destructor (`~ShellContent`) to `ShellContent` that unsubscribes from property change notifications, preventing memory leaks when a shared `Page` is assigned to multiple transient `ShellContent` instances (`src/Controls/src/Core/Shell/ShellContent.cs`). * Refactored event subscription logic to use `WeakNotifyPropertyChangedProxy` and a cached handler, ensuring that event handlers do not prevent garbage collection of `ShellContent` instances (`src/Controls/src/Core/Shell/ShellContent.cs`). **Testing and regression coverage:** * Adds a unit test to verify that assigning the same long-lived `Page` to many transient `ShellContent` instances does not retain those instances in memory, addressing issue #37217 (`src/Controls/tests/Core.UnitTests/ShellTests.cs`). **Public API updates:** * Adds destructor signature for `ShellContent` to the platform-specific `PublicAPI.Unshipped.txt` files to document the new public API surface (`src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt`, `src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt`, `src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt`, `src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt`, `src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt`, `src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Unshipped.txt`, `src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt`). [[1]](diffhunk://#diff-4731d7bdf78f0e9d2a7a64d6f56502e3d2095313d039e7f09c0e7d1552471f8eR25) [[2]](diffhunk://#diff-793476570313a2965972f9be2c01f3eaaf5eec16dfab1b6b7e34cd5473af4277R18) [[3]](diffhunk://#diff-b98fb401b945e281e04d9aabd0695677c639da1423ae935f1e521e88e8cae021R8) [[4]](diffhunk://#diff-923a9c83577000b182ef448083ba67a73bd622126eafbd11d265afe0e2387a68R10) <!-- 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 #37217 ### 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/c8166be4-b3b0-4706-8a38-ebfc6778f6ff"> | <video src="https://github.com/user-attachments/assets/c26f1915-2152-4c5e-b923-2659a5b13f3a"> | <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. -->
… to its condition by configuration/target (#37176) <!-- 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 MauiXaml will generate source for every xaml file without respect to its condition by configuration/target ### Root Cause • Microsoft.Maui.Controls.Globs.props globs **\*.xaml into the MauiXaml item group unconditionally for every inner build/TFM. • Microsoft.Maui.Controls.SingleProject.targets correctly gates Compile ( .cs ) items under Platforms/<Platform>/ via %(Compile.ExcludeFromCurrentConfiguration) , but its XAML-removal logic only ever stripped Windows .xaml (WinUI markup) out of MauiXaml . It never removed non-active-platform .xaml under Platforms/Android , Platforms/iOS , Platforms/MacCatalyst , or Platforms/Tizen . • Consequence: the XAML SourceGen consumes MauiXaml as AdditionalFiles regardless of platform, so every platform's xaml leaked into every inner build — producing duplicate InitializeComponent /attribute/field declarations whenever multiple platforms reused the same class name (a standard, supported pattern). ### Description of Change src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.SingleProject.targets (shipped via buildTransitive in Microsoft.Maui.Controls.Build.Tasks → applies to every MAUI app) Extended the _MauiRemovePlatformCompileItems target's _MauiXamlToRemove computation (previously Windows-only) to also cover Android/iOS/MacCatalyst/Tizen: for each built-in platform folder, its .xaml files are queued for removal from MauiXaml / EmbeddedResource unless it matches the currently active $(TargetPlatformIdentifier) . The pre-existing unconditional Windows-folder removal (WinUI markup, not MAUI XAML) is left unchanged. ### Issues Fixed Fixes #36951 **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | <img src="https://github.com/user-attachments/assets/a0fd36d9-2094-4948-a645-c3c0d1bf0e4e" Width="600" Height="300" /> | <img width="600" height="300" alt="image" src="https://github.com/user-attachments/assets/510d9024-dacc-4447-821d-29e7129ed844" /> |
### Description of Change Captures the weak-reference fields in local variables before testing and dereferencing them. This closes the time-of-check/time-of-use race with `Unsubscribe()`, which clears the fields concurrently. The race has been observed as an unhandled Android `NullReferenceException` from both `TryGetSource` during binding finalization and `TryGetHandler` while processing property changes. ### Issues Fixed Fixes #32602 ### Validation - `dotnet build src/Controls/src/Core/Controls.Core.csproj --no-restore --verbosity minimal -p:TargetFramework=netstandard2.0` Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
## Description Keeps `VisualElement.IsVisible` as the locally assigned/bound value while making handler-facing `IView.Visibility` reflect cumulative visibility through the visual ancestor chain. Effective visibility changes are cached and propagated through the existing property-propagation pipeline. Unchanged branches are pruned, so descendant handlers and measure invalidation run only for actual effective visibility transitions. Reparenting and detaching are covered. Fixes #19139. ## Regression tests - Hidden and nested ancestors - Ancestor visibility changes without mutating child `IsVisible` - Reparenting and detaching - Non-layout visual children - Handler mapping and unchanged-branch pruning - Measure invalidation ## Validation - `VisualElementTests`: 29 passed - `Issue1549` XAML compatibility tests: 3 passed - iOS runtime: `IsVisible` remains `True`, `IView.Visibility` is `Collapsed`, and keyboard Next skips the hidden entry - Android runtime: `IsVisible` remains `True`, `IView.Visibility` is `Collapsed`, and IME Next skips the hidden entry ---------
…eak Device Test (#37310) <!-- 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 Details Device memory leak tests started failing in the Candidate branch after PR #35487, indicating regressions in memory leak validation across Windows, iOS, macOS, and Android. The affected Does Not Leak and Window Does Not Leak tests were failing on these platforms. ### Issue1: Window Does Not Leak ### Root cause The WindowDoesNotLeak test failed intermittently because window and page were declared as locals inside an async Task method ( WindowDoesNotLeak ) and were referenced across await boundaries (both directly and inside the lambda passed to CreateHandlerAndAddToWindow ). The C# compiler hoists such locals into fields of the generated async state machine, and those fields are not guaranteed to be cleared once the locals are no longer needed. As a result, window and page remained artificially rooted by the state machine instance for the entire duration of the subsequent WaitForGC call, producing a false-positive "still alive" leak report rather than reflecting an actual product defect. ### Solution description The fix extracts the window/page creation and handler invocation logic out of WindowDoesNotLeak into a new, non-inlineable helper method, CreateWindowLeakReferencesAsync , marked with [MethodImpl(MethodImplOptions.NoInlining)] . This helper creates window and page , drives the handler lifecycle, and returns only the collected WeakReference list. Since window and page now live in the helper's own async state machine — which is discarded once the helper returns — they are no longer reachable from WindowDoesNotLeak 's state machine during the subsequent WaitForGC call, eliminating the artificial rooting. The dead conditional compilation guard ( #if TEST_FAILS_ON_ANDROID && TESTS_FAILS_ON_WINDOWS && TESTS_FAILS_ON_IOS && TESTS_FAILS_ON_MACCATALYST ) that had disabled the test was also removed to re-enable it. ### Issue2: TabbedPageTests.DoesNotLeak ### Root cause The issue occurs because of two compounding factors. At the test level, the navPage local was captured by an async lambda and accessed again after an await , causing it to be hoisted into the compiler-generated closure and transitively keep the popped TabbedPage alive through its navigation stack. At the platform level on Android, MultiPageFragmentStateAdapter was constructed using the host Activity's long-lived Lifecycle , causing AndroidX to permanently register a lifecycle observer that was never released because the Activity's lifecycle never reached the destroyed state. This kept the adapter, and the TabbedPage it referenced, permanently rooted in memory, while AndroidX also failed to reclaim the associated child fragments. ### Solution description The fix involves nulling the navPage local before the WaitForGC call at the test level, combined with a production-level Android fix in MultiPageFragmentStateAdapter.cs that introduces a teardown routine to make AndroidX reclaim its fragments correctly and explicitly clears the adapter's page reference on disposal. Supporting changes in TabbedPageManager.cs and TabbedPage.Android.cs ensure the teardown routine executes before the adapter is detached and that manager references are cleared on disconnect. The resolution was verified through repeated on-device Android test runs, all passing successfully. ### Issue3: NavigationPageTests.DoesNotLeak ### Root Cause The issue occurs because of the `navPage` and `window` locals in `NavigationPageTests.DoesNotLeak` being referenced across an `await` boundary — both directly and inside the lambda passed to `CreateHandlerAndAddToWindow`. The C# compiler hoists such locals into fields of the generated async state machine for the test method, and those fields are not guaranteed to be cleared once the locals are no longer needed. As a result, `navPage` and `window` remained artificially rooted by the state machine instance for the duration of the subsequent `WaitForGC` call, producing a false-positive "still alive" leak report rather than reflecting an actual product defect. This issue was only replicated in Release mode, since Release-mode JIT/compiler optimizations affect how and when the hoisted state-machine fields are cleared, whereas Debug builds happened to clear or avoid rooting them, masking the problem locally. ### Solution Description The fix involves extracting the `navPage`/`window` creation and handler invocation logic out of `DoesNotLeak` into a new, non-inlineable helper method, `CreateNavigationPageLeakReferencesAsync`, marked with `[MethodImpl(MethodImplOptions.NoInlining)]`. This helper creates `navPage` and `window`, drives the handler lifecycle, and returns only the collected `WeakReference` list. Since `navPage` and `window` now live in the helper's own async state machine — which is discarded once the helper returns — they are no longer reachable from `DoesNotLeak`'s state machine during the subsequent `WaitForGC` call, eliminating the artificial rooting. Validated the behavior in the following platforms - [x] iOS - [x] Mac - [x] Android - [x] Windows ### Regression PR PR #35487 ### Issues Fixed Fixes #36613 ### Output Screenshot ### Issue1: Window Does Not Leak |Platform|Before|After| |--|--|--| |Android| <video src="https://github.com/user-attachments/assets/1d3986aa-5c5f-4d97-ab6e-96c586e53488" >| <video src="https://github.com/user-attachments/assets/3670bafa-6a75-47a8-8505-797901e7abeb">| |Mac|<video src="https://github.com/user-attachments/assets/461534f8-21dd-46ab-bb62-c10a5f8ac71a"> |<video src="https://github.com/user-attachments/assets/d862eb7f-c33f-4866-a553-5264b1cda411">| |iOS|<video src="https://github.com/user-attachments/assets/41b71c49-26ac-4dcc-9e01-87dce42d5000">|<video src="https://github.com/user-attachments/assets/9e03f7ca-d803-49b9-a159-4057320591a7">| |Windows|<video src="https://github.com/user-attachments/assets/73300a73-a9be-403b-b77e-2cc4418d10c9">|<video src="https://github.com/user-attachments/assets/173cf2e3-5bde-4383-b07a-0b6b8422d03b"> | ### Issue2: TabbedPageTests.DoesNotLeak |Platform|Before|After| |--|--|--| |Android| <video src="https://github.com/user-attachments/assets/604316e5-5849-4195-9e16-1c96d710c125" >| <video src="https://github.com/user-attachments/assets/50bc614c-814d-43d1-912b-446886086886">| ### Issue3: NavigationPageTests.DoesNotLeak |Platform|Before|After| |--|--|--| |Mac|<video src="https://github.com/user-attachments/assets/cd6831a8-e8f6-4954-baff-055a2575a576"> |<video src="https://github.com/user-attachments/assets/6198e780-82e9-4eec-b3f5-a805f79d0ddd">| |iOS|<video src="https://github.com/user-attachments/assets/47edefd0-a416-4245-bbce-3e54c80aefa0">|<video src="https://github.com/user-attachments/assets/84f2c31c-0d9d-4c3e-9f21-9a8f634e671f">|
<!-- 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! On Windows, propagate `InputTransparent` to a view's `WrapperView` as well as its inner platform view. This allows pointer input to pass through wrapped controls, including the default-template `Label` with a transparent background overlaying a `Button` from #21384. The fix preserves two important Windows behaviors: - `ILayoutHandler` continues using `LayoutPanel`'s specialized background-based input transparency, so transparent layouts do not disable their interactive child tree. - Reusing a disconnected handler preserves the existing wrapper and its visual-tree position while replacing its stale child with the newly created platform view. Framework reconnect creates and connects the replacement platform view unparented before mapper replay. The reconnect repair therefore only updates `WrapperView.Child`; it does not remove the platform view from arbitrary parent shapes or re-enter virtual `SetupContainer()` overrides that could duplicate subscriptions or one-time setup. Normal mapper replay restores Label/Image sizing and alignment after the child replacement. The default template's implicit `Label` style supplies a transparent background, which causes `LabelHandler` to create a Windows `WrapperView`. The existing mapper disabled hit testing only on the inner `TextBlock`; the effective wrapper remained hit-testable and intercepted pointer input. - Windows Label device tests: **42 total, 40 passed, 0 failed, 2 skipped**. Coverage includes initial state, runtime toggles, late wrapper creation, reconnect hit testing and mapped properties, the framework's unparented replacement-platform-view lifecycle, a wrapper moved to another attached `Panel`, and a detached wrapper. - Failure-first reconnect validation: temporarily removing the reconnect rebinding made all three reconnect-specific tests fail; restoring it made them pass. - Windows Layout device tests: **54/54 passed**, covering both `CascadeInputTransparent` modes and confirming that the wrapper remains hit-testable for child interaction. - Windows Core tests: **1,980 passed, 0 failed, 111 skipped**; the exact CI-reported Slider case and all 90 Slider tests passed locally. - Windows Appium test and HostApp builds completed with **0 warnings and 0 errors**, and both Issue21384 tests are discovered. The reporter-faithful Label pointer test is skipped on MacCatalyst because test remains cross-platform. - Local Appium execution remains blocked before interaction by WinAppDriver's invalid status response. The real Win32 `SendInput` harness below provides behavior-level evidence. Both recordings use the same `AbsoluteLayout` reproduction from #21384 and send five real Win32 mouse clicks to the overlaid button (`SendInput`, not UI Automation invoke). **Before — bug reproduced on parent commit `f377ff1c5e`:** all five clicks are sent, but the click handler receives none and the visible counter remains at 0. https://github.com/user-attachments/assets/d59d3346-355c-434f-b1ac-01c76c361ab1 **After — fixed behavior:** all five equivalent clicks reach the button and the visible counter advances from 0 to 5. The final production code was rerun with the same harness and again received **5/5** clicks. https://github.com/user-attachments/assets/610856db-c094-4657-b4ea-0985b96221dd - Do not update only the inner Windows platform view; a hit-testable `WrapperView` can still intercept input. - Do not disable the wrapper for `ILayoutHandler`; `LayoutPanel` intentionally preserves child interaction through its background-based mapper. - Do not re-enter virtual `SetupContainer()` during reconnect; derived handlers may repeat subscriptions or one-time side effects. - Do not add generalized parent-detachment logic for reconnect; the framework replacement platform view is unparented before mapper replay, and the surviving wrapper's parent must remain unchanged. Fixes #21384 @owaits, once the build artifacts are available, could you please try them with your original reproduction and let us know whether this resolves the issue for you? --------- Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
… and callbacks alive (#37639) <!-- 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 Details - Disposing `AnimationManager` did not release the manager, active animations, or callback-captured data when its `ITicker` remained alive. ### Root Cause of the Issue - `AnimationManager` assigns `OnFire` to `Ticker.Fire` and stores active animations in `_animations`. Its previous `Dispose()` implementation only disposed tickers implementing `IDisposable`; it did not remove `OnFire`, stop a normal `ITicker`, or clear `_animations`. Consequently, a long-lived ticker could retain the entire object graph. ### Description of Change <!-- Enter description of the fix in this section --> ### Improvements to resource management and disposal: * Refactored the `Dispose` method in `AnimationManager` to ensure it is idempotent, detaches event handlers, clears animations, and disposes of the ticker only when appropriate. This prevents multiple disposals and ensures resources are released correctly. ### New unit tests for disposal behavior: * Added `AnimationManagerTests` with tests to verify: - The ticker callback is released without disposing the animation. - Animation payloads are released when the ticker outlives the manager. - The owned callback is properly removed from multicast delegates. - Correct disposal and stop counts for the ticker. - No unintended side effects on animation callbacks after disposal. ### 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 #37228 ### Tested the behavior in the following platforms - [x] Windows - [x] Android - [x] iOS - [x] Mac ### Output | Before | After | |----------|----------| | <img src="https://github.com/user-attachments/assets/fe7e8c32-eb2c-4808-bc8b-599aa7055344"> | <img src="https://github.com/user-attachments/assets/83fe5ec1-6462-4942-a461-034f3d25407b"> | <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. -->
<!-- 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! Fixes #17523 Windows attached the Border's `CompositionGeometricClip` directly to the content visual while authoring the geometry in the parent `ContentPanel` coordinate space. Scale, rotation, and translation therefore transformed the clip together with the content instead of keeping the Border aperture stationary. - Place Border content inside a Border-only stationary native clip host and attach the geometric clip to that host. - Route cross-platform measure invalidation to both native layers while preserving WinUI's cached subtree measure on unrelated parent layout passes. - Avoid re-entering measure from arrange when a layout owner changes; the normal invalidated measure pass remains authoritative. - Preserve the cross-platform arranged size through the native clip host, including detached and reconnected layout-owner transitions. - Cache stable composition and rectangular bounds clip geometry, rebuilding only when geometry inputs change. - Tear down layout owners, hosted content, stroke references, and cached clip state when the handler disconnects, after derived handler disconnect hooks have observed the intact platform view. - Safely ignore late invalidation after handler disconnect and synchronize direct or reconnect-driven layout-owner changes with the clip host. - Preserve current cross-parent content reparenting while clearing stale clip-host ownership when content moves Border → Border, Border → generic `MauiPanel`, or back again. - Handle zero-by-infinite WinUI measure constraints without invoking cross-platform layout. - Keep layout invalidation flowing for initial asynchronous image loads and runtime content-size, `FontSize`, and `Padding` changes without requiring an outer window resize. - Preserve explicit Border sizing, stroke/shadow behavior, nested layout clipping, content replacement, custom handler activation and mapper customization, shape removal, and accessibility behavior. - Clamp stroke-inset geometry to nonnegative dimensions and preserve an explicitly empty aperture when the stroke consumes all available content space, including rounded shapes. - Clear stale clipping geometry whenever either arranged dimension is non-positive. - Remove the obsolete nested `LayoutPanel` clip exception because the XAML rectangular clip and Border composition clip now live on separate visuals. - Update the three affected WinUI Image AspectFill baselines for the stationary clip host's one-pixel antialiased inner edge; image content remains pixel-identical. This is an implementation-only Windows fix; it adds no public APIs. **Before — issue author's attached reproduction, minimally retargeted to the current Windows TFM:** transformed image content escapes the stationary ellipse, rounded rectangle, and triangle apertures as image scale changes. https://github.com/user-attachments/assets/7cf6b0fc-c101-44df-ba5b-841131014708 **After — final reviewed PR gallery build using the exact `BorderResizeContent` source scenario:** the same scale interaction changes the image while each Border aperture remains stationary and correctly clips its content. https://github.com/user-attachments/assets/97a4429a-c32c-4c9f-9252-957b8f2c5e8f Both recordings use a 1280×720 window. Pixel analysis of the recorded scale-4 frames detected transformed image pixels outside the three Border regions before the fix and **0 outside after the fix**. - Windows Border device tests: **38 passed, 0 failed, 0 skipped, 0 errors**. - Added coverage for scale, rotation, translation, combined transforms, shadows, nested layouts, initial asynchronous image rendering, runtime `FontSize` and `Padding`, explicit sizing, content replacement, shape removal, disconnect/reconnect, derived disconnect ordering, teardown cleanup, direct layout-owner changes, derived handlers, clip ownership, cross-host and generic-parent reparenting, composition and bounds clip reuse, zero-by-infinite constraints, stroke-consuming zero-interior geometry, rounded empty apertures, cross-platform arranged-size propagation, automation, and layout-cache reuse. - Exact final `BorderResizeContent.xaml` gallery proof ran without resizing the window: - Image scale 1 → 4 changed 14,673 pixels inside the Border shapes and 0 outside. - Font size 40 → 120 changed 11,584 pixels inside the Border shapes and 0 outside. - All images rendered on initial load. - The repository's production `MagickNetVisualComparer` passes all three updated WinUI Image AspectFill snapshots at the default 0.005 RMS threshold. The accepted delta is confined to the one-pixel Border edge with zero changed pixels in the image interior. - Multiple independent MAUI expert, adversarial, and layout/performance reviews completed with no remaining actionable findings. @jstedfast, could you please test the PR artifacts against the original `BorderResizeContent` reproduction and confirm that initial rendering, transformed clipping, runtime font-size changes, and resizing now behave correctly? Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
…'s task (#37666) ### Description of Change Follow-up to #37409 (itself a follow-up to #37060), closing three holes of the same species in the deferred element-scroll machinery: **a request that ends without its task completing, or whose completion runs on the wrong stack.** Two are permanent hangs of `await ScrollToAsync(...)`; one is reachable by entirely ordinary code. 1. **A parked request displaced by any newer `ScrollToAsync` orphaned the first caller's task** — two calls in a row (say, both from `OnAppearing` before the first layout) and the first `await` never returns. Nothing else ever completes it: the superseding request creates a fresh completion source, and the `TaskStatus.Running` check in `CheckTaskCompletionSource` is dead code (a TCS-backed task reports `WaitingForActivation`, never `Running`, so the `TrySetCanceled` there is unreachable). This is the headline fix. 2. **Yielding the replay to a re-entrant `ScrollToRequested` subscriber abandoned the superseded caller's task** — same mechanism, narrower trigger (a legacy renderer issuing its own `ScrollToAsync` from inside the replayed event): permanent hang. 3. **The lifecycle-drop completion ran the caller's continuation from inside `Element.SetParent`**, before `OnPropertyChanged(nameof(Parent))` fires — caller code observing/mutating a half-propagated parent change. **One primitive fixes all three.** `CompleteWithoutScroll(completion)` captures the completion source **as a value** and posts `TrySetResult(true)` through the dispatcher: - **off the mutation stack** (fixes 3) — the continuation never runs inside `SetParent`/handler-change; - **bound by identity** (preserves the invariant from #37409's review rounds) — the post cannot read the field at fire time, so a newer request swapping `_scrollCompletionSource` in the window can never be released in the old request's place; - **applied at every point a request ends without its scroll** — the drop paths (detach, tree-removal, orphaned target), the yielded replay (fixes 2), and the supersede in `OnScrollToRequested` (fixes 1). The ordinary platform-callback completion (`SendScrollFinished` when a scroll actually happens) is untouched, so `await ScrollToAsync(...)` timing on the normal path is unchanged. Completing (rather than cancelling) a superseded task matches the existing drop semantics — no `await` in this API's history has thrown on supersede, and introducing `TaskCanceledException` would be a new public behavior. The contract comment now names all three exits from the park — replayed, superseded, dropped — so the stated contract and the code have no gap. No new public API. ### Issues Fixed Follow-up to #37409 / #37060 (fixes for #36801). ### Tests Every fix is pinned by a test **proven to fail with that fix reverted**: - `SupersedingAParkedRequestCompletesTheSupersededCallersTask` — both supersede shapes (direct send, and park-in-place) - `ReentrantRequestFromTheReplayedEventSupersedesTheReplay` — extended to assert the superseded caller is released - `DropCompletionIsPostedNotRunOnTheMutationStack` — dispatcher-capture harness: task pending after `Remove` returns, exactly one post queued, completes when it runs - `PostedDropCompletionReleasesOnlyTheDroppedTaskEvenIfANewRequestArrivesFirst` — the identity property: a new request arriving before the post runs is untouched; the dropped task completes (this test fails against a field-reading post, the bug shape from #37409's review) Verified on the merged `inflight/current` base: `ScrollViewUnitTests` 42/42 (10 consecutive runs), `Issue36801` + `Issue36801DeferredElement` + `ShellFlyoutHeaderScrollViewContent` iOS UI suites 12/12 on the simulator. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
… static event with WeakEventManager (#37382) <!-- 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 Details VisualDiagnostics.VisualTreeChanged is a public static event used by XAML Hot Reload, live visual-tree inspectors, and diagnostic tools. Because it is a plain multicast event, every subscriber is held by a strong reference in the invocation list. Any page, view, or object that subscribes stays alive until it explicitly calls -=, silently leaking the entire visual subtree, bindings, and view models. ### Root Cause The event was a normal static event — .NET stores subscribers with strong references. Since it's static, the list lives for the app's lifetime, so every subscriber lives forever too. The only way to escape was to explicitly write -=, which most callers forget. ### Description of Change Backed the event with a WeakEventManager (MAUI's built-in weak-event helper), so subscribers are held weakly and can be GC'd. The public event signature is unchanged — callers don't need to change anything. Validated the behavior in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Issues Fixed Fixes #37242 ### Fix reference : [maui/src/Controls/src/Core/Application/Application.cs at bf62313 · …](https://github.com/dotnet/maui/blob/bf62313db2cecf3215f10c353720b341aba0a4ee/src/Controls/src/Core/Application/Application.cs#L263) [maui/src/Controls/src/Core/Command.cs at bf62313 · dotnet/maui](https://github.com/dotnet/maui/blob/bf62313db2cecf3215f10c353720b341aba0a4ee/src/Controls/src/Core/Command.cs#L128) [maui/src/Controls/src/Core/ImageSource.cs at bf62313 · dotnet/maui](https://github.com/dotnet/maui/blob/bf62313db2cecf3215f10c353720b341aba0a4ee/src/Controls/src/Core/ImageSource.cs#L175) ### Output ScreenShot |Before|After| |--|--| | <video src="https://github.com/user-attachments/assets/8b1d453a-dedd-48d0-a01d-aae7c7523f82" >| <video src="https://github.com/user-attachments/assets/824df312-de3c-4c4e-b073-9239b7c9d5c9">|
<!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Description of Change On Windows, mouse-wheel scrolling could update `CarouselView.Position` from native `ScrollViewer` events and then feed that update back into an animated programmatic `ScrollTo`. Competing native and programmatic scroll paths could cause runaway scrolling or leave the selected item visibly off-center. This change: - suppresses only the exact `Position`/`CurrentItem` mapper callbacks produced by native scrolling and handler-originated collection reconciliation, while preserving application-driven nested updates and nesting the suppression state safely; - lets newer user/native input supersede active corrective recentering instead of swallowing it as part of the previous request; - treats a routed mouse-wheel event as immediate user intent, removing the timing window that could leave stale collection state active before `ViewChanging`; - uses the geometrically nearest visible item for both logical selection and terminal centering, with the native center index as a fallback while containers are realized; - defers terminal geometry until Windows has completed virtualized layout and versions queued work so newer input, application scrolling, collection updates, and disconnects invalidate stale callbacks; - recenters when Windows scrolling settles for centered `Mandatory` and `MandatorySingle` snap points and bounds corrective attempts when native coercion rejects a requested center; - preserves `KeepScrollOffset` reconciliation and synchronous application `Position` or `CurrentItem` overrides during collection updates, including reentrant `PositionChanged` updates; - validates native collection projection after layout, follows `Items.VectorChanged` progress without resetting the bounded retry budget, realizes offscreen override targets natively, and issues one final centered MAUI scroll; - reuses one retry timer within a handler connection, then stops, detaches, and releases it on disconnect so reconnect uses the new dispatcher; - makes repeated native `ScrollViewer` discovery idempotent and detaches routed/native handlers symmetrically on replacement and disconnect; - maps looped physical indexes to logical indexes, realizes looped targets in the central physical cycle, and keeps final centering in that high physical range without exposing `CenterMode` across asynchronous work; - resets all transient scroll, timer, pointer-input, initialization, loop-facade, and native collection subscription state across superseding input and handler disconnect/reconnect; - applies forward tie-breaking against the true minimum distance so the 1 px tolerance cannot compound; and - clamps target offsets at scroll boundaries. The fix is limited to the Windows CarouselView implementation. Native `None`, Start, and End snap behavior remains owned by WinUI. ### Validation Validated with the issue's linked reproduction at commit `cee7aee936214bbe7fa2a06ffec7d6d14876bb8c`, built against the final PR sources. Rapid forward wheel bursts, delayed tail input, and rapid reverse input each remained responsive and settled within 1 px of the viewport center. The Windows `CarouselView` device-test category now contains 45 tests. Added or strengthened coverage includes repeated `ScrollViewer` discovery, immediate wheel supersession, reentrant `PositionChanged` collection overrides, monotonic native-projection retry budgets, deterministic looped high-cycle realization/final centering, nested native-scroll attribution, retry-timer reuse, and disconnect/reconnect cleanup. - **controlled previous production handler:** 41 passed, 4 failed; the failures discriminate nested scroll attribution, retry-timer reuse, disconnect cleanup (including initialization and loop-facade state), and the redundant-layout collection path; - **test-first timer lifecycle check:** 44 passed, 1 failed before disconnect disposal; 45 passed, 0 failed after the fix; - **final local unpackaged Windows CarouselView suite:** 45 passed, 0 failed; - **final local real-packaged Windows CarouselView suite:** 45 passed, 0 failed; - **exact linked reproduction:** all three wheel scenarios settled within 1 px; and - **independent MAUI expert review:** found the cross-disconnect timer ownership issue above; re-review after its test-first fix was clean with no remaining findings. All test counts come from authoritative XML read after the test process exited. #### Before fix The card remains visibly displaced after scrolling (measured approximately 112 px from the viewport center). https://github.com/user-attachments/assets/ae6c8f6b-648e-4927-9591-4af9c27bd874 #### After fix The same interaction remains responsive and settles with the card centered (runtime validation tolerance was <=1 px). https://github.com/user-attachments/assets/1ea9a740-770c-4783-85c9-183e75cb9d96 ### Testing Requested @LaoR-UA, thank you for the reproduction and manual feedback. When CI publishes artifacts for this PR, could you please [try the resulting build](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) with your original project and let us know whether mouse-wheel scrolling now behaves correctly on your setup? ### Issues Fixed Fixes #35621 ---------
…e members (#36444) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Description of Change XAML Source Generation emitted direct member access for binding paths, so a `null` intermediate (for example, `{Binding A.B.C.Text}` where `A` or `B` is null at runtime) threw `NullReferenceException`. This diverged from runtime and XamlC bindings, which tolerate null intermediates. The root cause was that the generator based null-conditional access on nullable reference-type annotations. Those annotations are not enforced at runtime: a reference declared non-nullable can still be `null`. This change: - Uses runtime nullability for member, array-index, and indexer path parts, and propagates the resulting nullable type through generated getters, setters, handlers, and `TypedBinding<,>` arguments. - Keeps two-way bindings able to write `null` through null-tolerant paths. Reference-type endpoints assign with the null-forgiving operator to remain warning-free; non-nullable value types retain the existing null guard. - Handles value-type property and indexer intermediates with read-modify-write generation. The setter updates a captured copy and assigns it back through each property/indexer in reverse order, avoiding both CS1612 and silently dropped writes. - Identifies array elements from the receiver type. Array elements and value-type fields remain direct lvalues and are not captured. Getter output, before and after: ```csharp // A, B, and C are non-nullable-declared reference types getter: source => (source.A.B.C.Text, true), getter: source => (source.A?.B?.C?.Text, true), ``` The first hop remains non-conditional (`source.Foo`, not `source?.Foo`) because `TypedBinding.ApplyCore` invokes the getter only with a non-null source. Non-nullable value-type endpoints retain their `?? default` fallback so their binding property types do not change. ### Tests - Updated exact generated-code expectations for compiled bindings, indexers, and Maui13856. - Added coverage for non-nullable-declared reference intermediates. - Added coverage proving two-way paths still write `null`. - Added setter coverage for value-type properties, indexers, arrays, fields, and nested reverse-order copy-back. ### Issues Fixed Fixes #36313 --------- 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: Jonathan Peppers <jonathan.peppers@microsoft.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Co-authored-by: Simon Rozsival <simon@rozsival.com> Copilot-Session: 10f057bb-7603-49db-aaf3-707c0cf0ddff
…eservation Causing Phantom Scroll Range (#37765) > [!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! On iOS, a ScrollView configured with SafeAreaEdges="Container" incorrectly reserves the safe area twice, resulting in an additional phantom scroll range. When the content is smaller than the viewport, the ScrollView becomes unnecessarily scrollable. The extra scrollable area corresponds exactly to the combined safe-area insets (for example, 82 pt on an iPhone 11: 48 pt for the status bar and 34 pt for the home indicator). When the content is taller than the viewport, the same issue causes an unnecessary dead over-scroll space at the end of the content. The issue occurs because MauiScrollView.CrossPlatformArrange always pads the scroll content's measured size by the safe-area thickness when ContentInsetAdjustmentBehavior is not Automatic, without checking whether UIKit has already reserved the same space through AdjustedContentInset. As a result, when SafeAreaEdges="Container" is set and the native inset is active, the safe area is accounted for twice—once by UIKit and once by the manual padding. This inflates the content size beyond its actual bounds and produces a phantom scrollable range, even when the content should not be scrollable. The fix narrows the manual-padding condition so that it applies only when the native inset is genuinely inactive—that is, when SystemAdjustedContentInset is zero or ContentInsetAdjustmentBehavior is Never. In all other cases, UIKit's own inset is trusted to reserve the safe area, and the content size is left unchanged. This removes the double reservation for SafeAreaEdges="Container" while preserving the existing None and Automaticbehaviors. Tested the behavior in the following platforms. - [x] iOS - [x] Android - [ ] Mac - [ ] Windows Fixes #36800 |Before Fix|After Fix| |--|--| <video src="https://github.com/user-attachments/assets/19c064e4-4622-4d1d-992c-340a56fb948f"> |<video src="https://github.com/user-attachments/assets/57fa7cae-6e95-4573-885d-8f2979750f38">| --------- Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
…37648) <!-- Please keep the note below for people who 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 whether this change resolves your issue. Thank you! This pull request addresses issues with the accuracy of the `CanGoBack` and `CanGoForward` properties in the Windows WebView handler, ensuring that navigation state is correctly reflected and not stale. It also adds a regression test to prevent future issues with navigation history. ### Description of Change **Fixes and improvements to WebView navigation state:** * Updated the logic in `WebViewHandler.Windows.cs` to check `CoreWebView2.CanGoBack` and `CoreWebView2.CanGoForward` instead of relying solely on the WebView2 control properties, which could become stale and cause incorrect navigation behavior. * Enhanced the `UpdateCanGoBackForward` extension method in `WebViewExtensions.cs` to prefer the `CoreWebView2` navigation state for `CanGoBack` and `CanGoForward`, falling back to the control's properties only when necessary. **Testing and regression prevention:** * Added a new test, `CanGoBackIsFalseAfterReturningToFirstPage`, to verify that `CanGoBack` is set to false after navigating back to the first page, preventing regressions related to navigation history. <!-- 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 #37534 ### Tested the behavior in the following platforms - [x] Windows - [ ] Android - [ ] iOS - [ ] Mac | Before Issue Fix | After Issue Fix | |----------|----------| | <video src="https://github.com/user-attachments/assets/c6c4e68b-21ac-49cd-ad96-3f628c889674"> | <video src="https://github.com/user-attachments/assets/1a0fcee7-32d4-42a6-8003-25b89087e580"> | <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> ---------
…est (#37267) <!-- 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 - On iOS, an Image does not scale up on the unconstrained axis when only HeightRequest or WidthRequest is set—the unconstrained axis remains capped at its native size. This is most visible with HorizontalStackLayout + HeightRequest and VerticalStackLayout + WidthRequest. The reverse combinations can appear to work because the other axis is large enough to mask the same issue. On Android, the Image scales correctly with HeightRequest and WidthRequest in all cases. ### Root Cause - In SizeThatFitsImage (iOS), the scale factor for ScaleAspectFit images was calculated as Math.Min(imageWidth, widthConstraint) / imageWidth. This could never exceed 1 (since it always divides the image's own size by itself once the constraint is larger), so an image could shrink to fit a smaller space but could never grow beyond its native size, even when an explicit HeightRequest or WidthRequest requested a larger size, regardless of StackLayout orientation. ### Description of Change - Updated SizeThatFitsImage in ImageViewExtensions.cs to accept flags indicating whether width and height constraints are explicit, and to allow images to scale up to requested sizes when either is set, instead of capping at native size. - Modified GetDesiredSizeFromHandler in ViewHandlerExtensions.iOS.cs to pass explicitness flags to SizeThatFitsImage, ensuring correct sizing behavior for images with explicit size requests. ### Issues Fixed Fixes #12879 ### Validated the behaviour in the following platforms - [ ] Windows - [ ] Android - [x] iOS - [x] Mac ### Output | Before | After | ----------|----------| | <img src="https://github.com/user-attachments/assets/c592756b-d87f-40dd-9073-0a4e03add828"> | <img src="https://github.com/user-attachments/assets/c884d1d2-a048-44ee-b1d9-ac59b9c29daf"> |
…37772) <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> The issue was caused by a small view moved off-screen with TranslationY for a full-screen Shell navigation animation. This incorrectly preserved the top safe-area inset, creating the unwanted gap in the bottom sheet. https://github.com/dotnet/maui/blob/19a188896c0e518c0d201db181f67166c740724d/src/Core/src/Platform/Android/SafeAreaExtensions.cs#L175 On Android, moving a view outside the screen using TranslationY incorrectly adds top padding to the layout. <!-- Enter description of the fix in this section --> Updated Android vertical animation detection to treat only full-screen views as Shell navigation transitions. Smaller translated controls, are excluded so they no longer receive incorrect top safe-area padding. <!-- 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 #37418 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [ ] Windows - [x] iOS - [ ] Mac | Before | After | |---------|--------| | **Android**<br> <img src="https://github.com/user-attachments/assets/9a17e25d-4b59-4d33-9b22-014bb504e3a0" width="300" height="600"> | **Android**<br> <img src="https://github.com/user-attachments/assets/aef1bf14-dca6-411f-94e4-c473ac3b5d0c" width="300" height="600"> | --------- Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
<!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Description of Change On Windows, WinUI's initial focus routing can select the first focusable descendant of a `ScrollViewer`. When a page opens with an `Entry` inside a scrollable MAUI `ScrollView`, that can focus the `Entry` and raise its `Focused` event without user input. The Windows handler now makes the native `ScrollViewer` a **transient** tab stop from WinUI's `Loading` event, giving the load-time focus pass a non-content target. A queued callback restores the original native, styled, locally customized, or bound `IsTabStop` state after load, so the ScrollViewer does not become a permanent keyboard or Narrator stop. A low-priority fail-safe queued from `Loading` also restores the transient state if the ScrollViewer leaves the native visual tree before either `Loaded` or `Unloaded` fires. The normal `Loaded` callback supersedes that fail-safe through a generation guard and restores on the next dispatcher turn. The temporary value is represented by an owned binding: if an app or mapper writes the native property before restore, that write replaces the binding and wins. Generation plus platform-view identity checks prevent stale callbacks from mutating a disconnected or replaced handler. Cleanup and restoration intentionally happen before `base.DisconnectHandler`, while the platform view and handler ownership are still valid; all lifecycle events are unsubscribed before base teardown. The shared Windows unfocus path preserves the original binding/local/style/default ownership of `IsTabStop`, so an unfocus operation during the temporary window cannot convert the transient value into a permanent local tab stop. Bindings are detached before the temporary `false` write so TwoWay sources are not mutated, then the original binding object is reinstated. No public API is added or changed. ### What NOT to Do - Do not make the internal `ContentPanel` a tab stop: it creates an invisible, unannounced keyboard stop. - Do not leave `ScrollViewer.IsTabStop=true` permanently: that changes steady-state tab order and accessibility for every Windows ScrollView. - Do not set `AllowFocusOnInteraction=false`: empirical testing showed that it also prevents legitimate pointer focus of child Entries. - Do not restore a hardcoded `IsTabStop` value: doing so destroys style, binding, and custom handler/mapper ownership. - Do not write a temporary dependency-property value while a TwoWay binding is attached: that pushes the temporary value into the source. - Do not use a normal-priority fail-safe from `Loading`: it can run before WinUI reaches `Loaded`, restoring too early and reintroducing automatic Entry focus. The fail-safe must remain low priority. - Do not synchronously restore when the low-priority `Loading` enqueue fails: empirical testing showed that removing the transient target during `Loading` recreates automatic Entry focus. Dispatcher shutdown remains covered by synchronous handler disconnect cleanup. - Do not cancel `GettingFocus` to identify automatic focus: WinUI reports both automatic and legitimate app requests as programmatic focus, so that signal cannot distinguish them safely. ### Issues Fixed Fixes #31039 ### Validation - Windows Controls `ScrollView` device tests with the fix: **26 passed, 0 failed**. Coverage includes direct transient activation, lifecycle ordering through `Loaded`, negative startup focus with a preceding Button and two sibling ScrollViews, native/default/local/style/OneWay/TwoWay ownership, binding detachment, TwoWay source and binding identity, later native writes, unfocus during the transient window, explicit focus, disconnect/reconnect, unload/reload, stale callbacks, native focused-element state, rooted Tab and Shift+Tab navigation, and removal from the native visual tree during `Loading` before `Loaded`/`Unloaded`. - Controlled sensitivity with only production `Loading` activation disabled: **20 passed, 6 failed**. The discriminating failures are startup focus, preceding-control/two-ScrollView startup focus, navigation reload, transient ordering, reverse navigation from the startup ScrollViewer, and custom local-value restoration. - Windows Controls `Entry` device tests: **54 passed, 0 failed, 4 skipped**. A non-ScrollView regression test verifies that programmatic Unfocus preserves style ownership and tracks a later style replacement. - The issue author's exact attached sample was rebuilt against the unchanged production implementation represented by head `21d3526a1b` and automated with UI Automation plus real pointer/keyboard input: - startup focus is the native ScrollViewer UIA `Pane`, exposed as a control/content element; no Entry focus and no alert; - clicking a normal Entry focuses it; - Tab advances to the next Entry; - Shift+Tab returns to the previous Entry; - clicking an `InputTransparent` Entry does not raise the first Entry's focus alert. - Independent MAUI-specialist and adversarial lifecycle reviews found no remaining high-confidence defect after the added fail-safe and discriminating coverage. - Optional device build 1565839 contained one unrelated MacCatalyst CarouselView leak failure; its osx.26 Helix job passed. Optional UI build 1565837 had broad cross-platform baseline failures also present on adjacent main builds. Required main build 1565836 passed. ### Empirical Proof **Before — untouched attached sample (MAUI 9.0.14):** https://github.com/user-attachments/assets/fc1c44f3-e385-4808-9f00-9694b83e127f **After — exact sample rebuilt against the transient fix:** https://github.com/user-attachments/assets/af84a6c5-97e1-4ddd-a89f-3730748b8cf2 @Kamalesh-Periyasamy, once the updated PR artifacts are available, please try them with your original reproduction and let us know whether this resolves the issue for you. --------- Copilot-Session: bcd06486-88bb-4458-ad38-55bf1be162f5
…37111) This pull request makes several improvements to the Entry control test pages and their supporting view models, focusing on expanding test coverage, improving UI accessibility, and enhancing code maintainability. The most significant changes include adding new bindable properties (such as `BackgroundColor`, `Opacity`, and `WidthRequest`), updating event handler logic for better testability, and refining the ViewModel with new helpers and a reset method. Additionally, UI elements have been updated for consistency and accessibility. **Feature and UI enhancements:** * Added bindable properties `BackgroundColor`, `Opacity`, and `WidthRequest` to the Entry controls and ViewModel, allowing these properties to be set and tested from the UI (`EntryControlPage.xaml`, `Material3_EntryControlPage.xaml`, `EntryViewModel.cs`). [[1]](diffhunk://#diff-14e7f146267aafe278aab3e4cec14f9fc100e09ae21886569c33bffba87cff28R42-R44) [[2]](diffhunk://#diff-f5e3ee56e4135c8dfd05cfce9bf234d413b52c8b6ce864a4ba0fca1ad004cc75R42-R44) [[3]](diffhunk://#diff-3f677ed4c454a245e3e82416c1a86b24aa0ade96b3b809d4cbedd7bc75534536L28-R32) [[4]](diffhunk://#diff-3f677ed4c454a245e3e82416c1a86b24aa0ade96b3b809d4cbedd7bc75534536R180-R213) * Added new labels to display the current keyboard type and return type in the UI, and updated the ViewModel to provide these values (`EntryControlPage.xaml`, `EntryViewModel.cs`). [[1]](diffhunk://#diff-14e7f146267aafe278aab3e4cec14f9fc100e09ae21886569c33bffba87cff28L100-R131) [[2]](diffhunk://#diff-3f677ed4c454a245e3e82416c1a86b24aa0ade96b3b809d4cbedd7bc75534536L124-R136) [[3]](diffhunk://#diff-3f677ed4c454a245e3e82416c1a86b24aa0ade96b3b809d4cbedd7bc75534536R180-R213) **Event handler and logic improvements:** * Updated event handlers to use `TextChanged` events for properties like cursor position, selection length, max length, width request, opacity, and height request, improving testability and code clarity (`EntryControlPage.xaml.cs`, `EntryOptionsPage.xaml.cs`). [[1]](diffhunk://#diff-976ce0c4d44779d336f56a5b66c3d1d02d6b59783311ee99efb4f5d1eb58317fL39-L54) [[2]](diffhunk://#diff-07ad3578095d6b7e4ef419d6921a7d43b5319bfd2970f669cb006118d1677de7L124-R134) [[3]](diffhunk://#diff-07ad3578095d6b7e4ef419d6921a7d43b5319bfd2970f669cb006118d1677de7L259-R318) * Refactored color selection logic for text and placeholder colors to use `AutomationId` instead of background color, increasing reliability in UI tests (`EntryOptionsPage.xaml.cs`). [[1]](diffhunk://#diff-07ad3578095d6b7e4ef419d6921a7d43b5319bfd2970f669cb006118d1677de7L26-R31) [[2]](diffhunk://#diff-07ad3578095d6b7e4ef419d6921a7d43b5319bfd2970f669cb006118d1677de7L50-R60) * Added a new reset method to the ViewModel to restore all properties to their default values, and updated the navigation logic to call this method (`EntryViewModel.cs`, `EntryControlPage.xaml.cs`). [[1]](diffhunk://#diff-3f677ed4c454a245e3e82416c1a86b24aa0ade96b3b809d4cbedd7bc75534536R312-R348) [[2]](diffhunk://#diff-976ce0c4d44779d336f56a5b66c3d1d02d6b59783311ee99efb4f5d1eb58317fL39-L54) **UI and accessibility updates:** * Added `AutomationId` values to key UI elements for improved automated testing and accessibility (`EntryControlPage.xaml`, `Material3_EntryControlPage.xaml`). [[1]](diffhunk://#diff-14e7f146267aafe278aab3e4cec14f9fc100e09ae21886569c33bffba87cff28R10-L13) [[2]](diffhunk://#diff-f5e3ee56e4135c8dfd05cfce9bf234d413b52c8b6ce864a4ba0fca1ad004cc75L8-L20) * Adjusted font sizes for consistency and improved label clarity, and reorganized UI elements for better structure and accessibility (`EntryControlPage.xaml`). [[1]](diffhunk://#diff-14e7f146267aafe278aab3e4cec14f9fc100e09ae21886569c33bffba87cff28L70-R78) [[2]](diffhunk://#diff-14e7f146267aafe278aab3e4cec14f9fc100e09ae21886569c33bffba87cff28L100-R131) These changes collectively improve the testability, maintainability, and accessibility of the Entry control test pages. Issue Identified: - #34611 - #29805 --------- Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
<!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ## Description Enables `AllowDrop` on the Windows BlazorWebView's underlying WinUI `WebView2` so external files dragged from Explorer can reach HTML drop targets. This addresses the Windows external-file-drop portion of #2205. Native in-page HTML element and image dragging remains blocked by upstream WinUI/WebView2 behavior and is outside the scope of this change. A cross-host repro and compatibility matrix are available at https://github.com/danroth27/BlazorHybridDragDrop. ## Testing - Added a Windows device test that verifies the created platform WebView2 has `AllowDrop` enabled. - Windows BlazorWebView device tests: 18 passed, 4 skipped, 0 failed. Fixes #37903 Copilot-Session: 6ecbe107-8703-4352-a1c6-e4f722cb9b28
<!-- 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 Details When ScrollView.Orientation="Horizontal" on Android, the content unexpectedly scrolls a few pixels vertically too, even though only horizontal scrolling was requested. ### Root Cause Android's outer scroll container calculates vertical scroll range using its inner horizontal-scroll child's height vs. its own padded content area. MAUI's code sized that inner child using the full (unpadded) outer height, leaving a small leftover gap equal to the padding — causing phantom vertical scroll. ### Description of Change In MauiScrollView.cs , OnMeasure / OnLayout now subtract PaddingTop/Bottom/Left/Right when sizing the inner horizontal scroll view, and offset its layout position by PaddingLeft/Top . This makes the inner view exactly match the true content area, eliminating the leftover scroll range. Validated the behavior in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Issues Fixed Fixes #37335 ### Output ScreenShot |Before|After| |--|--| | <video src="https://github.com/user-attachments/assets/677494c4-4e09-4e1b-af46-eeb48a3c2f7a" >| <video src="https://github.com/user-attachments/assets/0180fcf3-6c7e-482b-bad0-7893e0838aa9">|
<!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Description of Change Marks `MauiWinUIApplication.Services` and `MauiWinUIApplication.Application` obsolete with actionable guidance to use `IPlatformApplication.Current` instead. This aligns Windows with the existing Android, iOS/MacCatalyst, and Tizen API surface and removes the overdue .NET 9 TODOs. ### Rationale PR #16803 moved framework internals away from concrete native application hosts to support embedding scenarios and originally deprecated these properties. PR #17667 deferred the Windows annotations because the WinUI XAML generator surfaced obsolete warnings from generated accessors. The current WinUI XAML generator now wraps generated obsolete-property accesses in `#pragma warning disable 0618`, so default projects no longer receive those warnings. Handwritten consumers still receive the intended migration warning. No `PublicAPI` baseline update is required because the property signatures are unchanged and obsolete attributes are not represented by the current baseline format. ### Validation - Built `Core.csproj` for `net10.0-windows10.0.19041.0` - Built `Core.csproj` for `net10.0-windows10.0.20348.0` - Rebuilt the Windows Sandbox app and confirmed generated accessors produce no `CS0618` or `RS0030` warnings --------- Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
<!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ## Summary - use the type-safe `Bundle.GetParcelable` overload for `WebAuthenticatorIntermediateActivity` on Android API 33 and newer - preserve the obsolete overload for Android API 21-32 - document why `ActivationState` must retain generic `Bundle.Get` access to preserve arbitrary value stringification - remove obsolete and platform warning suppressions where the typed overload makes them unnecessary ## Validation - `dotnet build src\Essentials\src\Essentials.csproj -f net10.0-android36.0 --no-restore --nologo -v:minimal` — 0 warnings, 0 errors - `dotnet build src\Core\src\Core.csproj -f net10.0-android36.0 --no-restore --nologo -v:minimal` — succeeded with only the existing Gradle Java 8 source/target warnings - `pwsh .github\skills\run-device-tests\scripts\Run-DeviceTests.ps1 -Project Essentials -Platform android -BuildOnly` — succeeded and produced the signed APK No Android emulator was available on the Windows validation host, so API 21-32 and API 33+ Activity recreation paths were not runtime-executed. The implementation follows the existing `IntermediateActivity` compatibility pattern. --------- Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
<!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ## Description Fixes #37429. On iOS, grouped `CollectionView` used the flattened leaf-item count to control `EmptyView` visibility. Removing the final item from an existing group therefore displayed `EmptyView` over a group that still existed. Grouped sources now use the outer `GroupCount`, so `EmptyView` remains hidden while any group exists and appears only after the final group is removed. The fix applies to both iOS handler generations: the legacy `CollectionViewHandler` and current `CollectionViewHandler2`. Each handler also retains a separate leaf-item emptiness signal so measurement and cache behavior is not coupled to group-level `EmptyView` state. This is the iOS-specific split of closed #37439, which maintainers requested be separated by platform. It intentionally contains no Android changes. ## Tests Added iOS device tests for both handlers using eventual assertions. They cover the reported populated-group-to-empty-group transition, verify that `EmptyView` does not overlay the remaining empty group after its final item is removed, verify that removing the final group shows `EmptyView`, and verify that adding an empty group hides it again. The iOS Debug device-test bundle builds successfully on Xcode 26.4. Local simulator execution could not complete because the installed XHarness 9 CLI cannot enumerate Xcode 26.4 simulators (exit code 71). ---------
<!-- 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 Details Removing a StateTriggerBase from VisualState.StateTriggers does not detach the trigger. If it subscribed to a long-lived event, the subscription can retain the trigger and its referenced objects. For example, calling state.StateTriggers.Clear() removes the trigger from the collection without calling its detach lifecycle. ### Root Cause VisualState.StateTriggers uses WatchAddList<StateTriggerBase>, which previously notified only when triggers were added. Operations such as Clear(), Remove(), RemoveAt(), and replacement therefore removed triggers without calling SendDetached(). ### Description of Change Updated WatchAddList<T> to support an optional removal callback and added removal handling to VisualState. Removed triggers are detached, their VisualState references are cleared, and active triggers are recalculated. Added regression coverage for Clear(), Remove(), RemoveAt(), and index replacement to verify that each removed trigger is detached exactly once. Validated the behavior in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Issues Fixed Fixes #38243 ### Output ScreenShot |Before|After| |--|--| | <img width="364" height="733" alt="image" src="https://github.com/user-attachments/assets/e2287141-a2b5-4791-970c-a5301b266b6b" /> | <img width="364" height="733" alt="image" src="https://github.com/user-attachments/assets/44aa8172-94ae-4698-96bd-2959981ccb4a" /> |
<!-- 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! ## Summary Allow `Microsoft.Maui.Controls.Xaml` to participate in trimming on modern .NET targets and remove its legacy assembly-level `[Preserve]` attribute. Source-generated XAML applications do not need the runtime XAML parser. Previously, `Controls.Xaml.csproj` set `<IsTrimmable>false</IsTrimmable>`, so the default partial-trim Android publish copied the complete assembly and retained `XamlLoader`, `XamlParser`, and their XML dependencies. This change sets `IsTrimmable` only for non-netstandard targets. The condition avoids `NETSDK1212` for the netstandard builds, where trimming metadata is unsupported. No replacement roots or preservation annotations were added: direct references to runtime XAML entry points retain the parser call graph, while unused runtime parsing is removed. ## Android size measurements Controlled .NET 11 `dotnet new maui --sample-content` Android arm64 publishes used an isolated NuGet package cache and replaced only `Microsoft.Maui.Controls.Xaml.dll` with locally built before/after binaries. Both publishes used the template-default `TrimMode=partial` and `PublishReadyToRun=false`. | Measurement | Before | After | Delta | |---|---:|---:|---:| | APK | 21,375,536 B | 21,313,030 B | **-62,506 B (-0.29%)** | | `Microsoft.Maui.Controls.Xaml.dll` | 125,952 B | 26,624 B | **-99,328 B** | | `XamlLoader` / `XamlParser` | Present | **Absent** | Removed | | `System.Xml.ReaderWriter.dll` | 5,120 B | 5,120 B | Unchanged | | `System.Private.Xml.dll` | 396,288 B | 381,440 B | **-14,848 B** | | `Microsoft.Maui.Controls.dll` | 1,414,144 B | 1,397,248 B | **-16,896 B** | `System.Xml.ReaderWriter` remains in the default partial-trim publish, but disappears under `TrimMode=full`. `System.Private.Xml` becomes smaller but remains because the sample-content app has independent references from Controls, Mono.Android, Syncfusion, AndroidX, and application code. The source-generated sample-content APK was installed and launched successfully on a physical Android device after trimming removed `XamlLoader` and `XamlParser`. ## Runtime XAML compatibility A separate default partial-trim publish directly called: ```csharp new ContentPage().LoadFromXaml("<ContentPage ...><Label ... /></ContentPage>"); ``` The linker retained the runtime parser without assembly-wide preservation: - `Microsoft.Maui.Controls.Xaml.dll`: 94,720 B - `XamlLoader` / `XamlParser`: present - `System.Xml.ReaderWriter.dll`: 5,120 B - `System.Private.Xml.dll`: 395,776 B That APK also installed and launched successfully on a physical Android device. Runtime XAML remains annotated with `RequiresUnreferencedCode`; applications that reference types only through runtime XAML may still need application-specific preservation. A full-trim publish reports the existing expected `IL2026` warning at the `LoadFromXaml` call site. Hot reload uses runtime XAML in non-trimmed development builds. Its resource-loading tests continue to pass; no hot-reload-specific root was required. ## Validation - `dotnet build src/Controls/src/Xaml/Controls.Xaml.csproj -c Release -f net10.0` — succeeded with no warnings - `dotnet build src/Controls/src/Xaml/Controls.Xaml.csproj -c Release -f netstandard2.0` — succeeded with no warnings - XAML `LoaderTests` — 39 passed - Hot-reload resource tests (`HRTests`) — 3 passed - Default partial-trim source-generated sample-content publish and physical Android launch - Default partial-trim direct `LoadFromXaml` publish and physical Android launch - Full-trim before/after comparison confirmed the legacy `PreserveAttribute` was not honored as a whole-assembly root by the current linker ---------
…or Shell/TabbedPage appearance under Material 3 (#37147) <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Description When Material 3 is enabled via <UseMaterial3>true</UseMaterial3>, Android Shell top tabs correctly show the selected state, but the selected indicator color does not match the Material 3 tabs specification. ### Root Cause Android Shell/TabbedPage rendering (`ShellToolbarAppearanceTracker`,` ShellTabLayoutAppearanceTracker`, `ShellBottomNavViewAppearanceTracker`, `TabbedPageManager`) fell back to hardcoded default colors whenever a Shell.TabBar*/appearance color property was null. Under Material 3, this hardcoded fallback overrode the native M3 theme's own default colors (colorPrimary, colorOnSurface, etc.), so M3 apps never displayed correct theme colors on the Shell toolbar, top tabs (TabLayout), or bottom navigation (BottomNavigationView) unless every single color was explicitly set. ### Description of Change - Each Android tracker captures the platform view's native/theme-provided color or background once, before any custom appearance is ever applied to it. - When a `Shell.TabBar*` color is later cleared back to null (e.g. removing a custom appearance), the tracker restores the originally-captured native value instead of substituting a hardcoded color. - This means M3 apps now correctly fall back to their native theme colors — matching platform conventions — rather than being forced into an unrelated hardcoded palette. ### Issues Fixed Fixes #35126 ### Tested the behaviour in the following platforms - [x] Android - [ ] Windows - [ ] iOS - [ ] Mac ### Output Screenshot Case| Light Theme | Dark Theme | |----------|----------|----------| | **Before**|<image width="100" height="200" alt="Image" src="https://github.com/user-attachments/assets/e8a6cc5f-5101-4d8d-9f0b-b199710b5da8">|<image width="100" height="200" alt="After Fix" src ="https://github.com/user-attachments/assets/23b6e57c-34fd-48d3-8c92-0b18f2df4ea9">| | **After** |<image width="100" height="200" alt="Image" src="https://github.com/user-attachments/assets/d732e3bc-6a53-4cd8-93a9-c559576d0d5c">|<image width="100" height="200" alt="After Fix" src ="https://github.com/user-attachments/assets/9c6ebe0f-b7ce-4d24-8d76-cad6f25cd785">|
<!-- Please keep the note below for people who 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 whether this change resolves your issue. Thank you! ### Root Cause The default `NavigationPage` and `TabbedPage` styles in `Styles.xaml` were not configured to apply to derived types. As a result, custom pages inheriting from these controls did not receive the default style setters and theme bindings. <!-- Enter description of the fix in this section --> ### Description of change - Added `ApplyToDerivedTypes="True"` to the default `NavigationPage` style. - Added `ApplyToDerivedTypes="True"` to the default `TabbedPage` style. This ensures that derived pages receive the expected default colors and AppThemeBinding values, including updates when the application theme changes. ### 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 #38400 ### 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/b706345f-1fd2-4fcc-8fe0-36388bddfc81"> | <video src="https://github.com/user-attachments/assets/af009220-a470-4ce4-82b0-e294895f0756"> | <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. -->
<!-- Please keep the note below for people who 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 whether this change resolves your issue. Thank you! ### Root cause : - `UpdateTabBarVisibility()` was always assigning `MauiNavigationView.PaneDisplayMode`, even when the requested value was already the current value. - Reassigning the same value unnecessarily causes the navigation view to process the pane-display-mode change again. - This interferes with the end portion of the TabBar transition animation. The start animation can be observed, but the redundant `PaneDisplayMode` update prevents the transition from completing normally. ### Description of change - Added a check in `UpdateTabBarVisibility` to compare the current `PaneDisplayMode` with the requested value before updating it. - This prevents redundant native property updates and allows the TabBar transition to complete normally, including the end animation. ### Why Test not added ? - Automated test is not added because the indicator’s end animation cannot be captured reliably through automation. Manual verification is required to validate the final animation state <!-- 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 #38422 ### Tested the behavior in the following platforms - [x] Windows - [ ] Android - [ ] iOS - [ ] Mac | Before Issue Fix | After Issue Fix | |----------|----------| | <video src="https://github.com/user-attachments/assets/63862d31-4ebb-4535-878d-59dafeb1e7c9"> | <video src="https://github.com/user-attachments/assets/c68fbfe2-9905-4d89-a8f3-a868cfae7d36"> | <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. -->
<!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Description of Change This change lets the XAML source generator compile common `{OnIdiom ...}` markup-extension usages as the existing strongly typed `OnIdiom<T>` type. For example: ```xml <Label Text="{OnIdiom Default=Default, Phone=Phone}" /> <Grid Margin="{OnIdiom '1,2,3,4', Desktop='5,6,7,8'}" /> ``` SourceGen can determine the target property types (`string` and `Thickness`) and generate typed `OnIdiom<string>` and `OnIdiom<Thickness>` instances instead of constructing `OnIdiomExtension` and calling `ProvideValue` at runtime. ### Motivation `OnIdiomExtension` must discover the target property type and perform conversion at runtime. Its constructor is therefore annotated with `RequiresUnreferencedCode`: > The OnIdiomExtension is not trim safe. Use OnIdiom<T> instead. When SourceGen emits `new OnIdiomExtension()` for ordinary XAML such as template styles, full-trim and NativeAOT builds report IL2026 even though the target type is already known to the XAML compiler. This became more visible after #38613 allowed unused runtime XAML infrastructure to be trimmed from source-generated applications. The compiler should avoid retaining and warning about the reflection-based path where it can produce equivalent typed code instead. ### Implementation A new `InferOnIdiomTypeArgumentsVisitor` runs after markup expansion and `OnPlatform` simplification, but before values are created. It: 1. Finds parsed `OnIdiomExtension` nodes used as property values. 2. Resolves the target CLR property or `BindableProperty` type, including attached properties and `Setter.Value`. 3. Verifies that the usage is within a conservative, behavior-preserving subset. 4. Replaces the node with a constructed `OnIdiom<T>` node registered in SourceGen's type cache. 5. Lets the existing SourceGen conversion and property-assignment pipeline emit the typed values. The generated code therefore avoids constructing `OnIdiomExtension`, avoids its service provider and runtime property discovery, and does not produce the associated IL2026 warning. ### Supported inference cases Inference is intentionally limited to target types whose conversion behavior SourceGen owns and can reproduce without consulting arbitrary application code: - C# scalar types such as `string`, integral types, `float`, `double`, `decimal`, `bool`, `char`, and `DateTime`; - `TimeSpan` and `Uri`; - enums defined by MAUI assemblies; - built-in MAUI types with a type-level converter already implemented by SourceGen, such as `Thickness`, `GridLength`, `CornerRadius`, `Color`, `Point`, `Rect`, `LayoutOptions`, and similar known types; - numeric values on MAUI font-size properties using the exact built-in `FontSizeConverter`. The tests cover CLR properties, bindable properties, attached properties, style setters, nested simplified `OnPlatform`, built-in MAUI converters, and numeric literal suffixes for `float`, `double`, `decimal`, `uint`, `long`, and `ulong`. ### Limitations and deliberate fallbacks SourceGen keeps using `OnIdiomExtension` when it cannot prove the typed transformation is equivalent. These cases continue to produce the existing trim warning so the application can decide whether to rewrite the XAML explicitly. #### Custom target types Custom application and third-party types are not inferred, even if they expose an implicit conversion from `string`. Such types can have conversion behavior that is not represented by SourceGen's built-in conversion pipeline. #### Custom property converters Properties with custom `TypeConverter` attributes are not compiled to `OnIdiom<T>`. A custom converter may attach semantics to otherwise ordinary values—for example, a converter could scale `"10"`, resolve a resource, or depend on `IProvideValueTarget`. Directly assigning `10` to `OnIdiom<double>` would silently bypass that behavior. The only property-level converter exception is MAUI's exact `FontSizeConverter`, and only when every value is an invariant numeric literal. Named font sizes such as `Medium` and `Large`, empty values, and expressions remain on the runtime extension path. #### Source-generated bindable properties in setters For `Setter.Value`, inference requires an actual resolved `BindableProperty` symbol. The existing heuristic for bindable properties produced by another source generator can identify the property name and type, but cannot reliably preserve all converter metadata, so those setters deliberately fall back. #### Runtime markup values and converters Nested markup extensions such as bindings or resources, explicit `Converter`/`ConverterParameter`, object-typed targets, and usages without a `Default` value remain `OnIdiomExtension` usages. A missing `Default` is significant because `OnIdiomExtension` can return a bindable property's registered default value, while `OnIdiom<T>` returns `default(T)`. ### Behavioral compatibility `OnIdiom<T>` previously treated every unrecognized idiom as Phone, while `OnIdiomExtension` returned `Default` for `DeviceIdiom.Unknown` and custom idioms created with `DeviceIdiom.Create(...)`. Because SourceGen now substitutes one implementation for the other, this PR aligns `OnIdiom<T>` with the markup extension: Phone is selected only for `DeviceIdiom.Phone`; unknown and custom idioms use `Default`. ### What NOT to Do - Do not infer every type merely because SourceGen can emit a syntactically valid assignment. Runtime converters may have additional semantics. - Do not map `object` targets to `OnIdiom<object>`; the standard reference conversion assigns the wrapper rather than invoking the generic implicit operator. - Do not duplicate the reflection-based implementation in a new `OnIdiomExtension<T>`. The existing `OnIdiom<T>` is sufficient for the safe subset and avoids maintaining two extension implementations. - Do not infer setter types from bindable-property heuristics unless converter metadata can also be proven complete. ### Related work - Closes #22142, which proposed compiling non-generic `{OnIdiom}` usages into `OnIdiom<T>` when the target type is known. - Supersedes the closed WIP #28700. That approach modified legacy IL XamlC and introduced a duplicated generic markup-extension implementation; this PR instead targets the current source generator and reuses the existing public `OnIdiom<T>` type. - #21927 originally enabled trimming analysis in `Microsoft.Maui.Controls.Xaml` and identified this follow-up. - #38613 made unused runtime XAML code trimmable, increasing the value of keeping source-generated applications off reflection-based markup-extension paths. - Related to the broader trimming effort tracked by #18658. ### Issues Fixed Closes #22142 ### Tests - SourceGen unit suite: 228 passed with the local .NET 11 target override; the three net11-specific `AppThemeBinding` golden-output tests were excluded because the project normally targets .NET 10 and the machine does not have the .NET 10 runtime. - Focused `OnIdiom<T>` runtime fallback test passed for Tablet, Watch, Unknown, and a custom idiom. - Added SourceGen regression coverage proving unsupported/custom conversion paths retain `OnIdiomExtension`. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…8587) <!-- 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 Details On Android with Material 3, an Editor starts at its maximum height instead of growing as text is entered. ### Root Cause The Editor was forced to use all available height, changing MaximumHeightRequest from a limit into its starting height. ### Description of Change Force the available height only for single-line controls such as Entry, allowing the multiline Editor to grow with its content. Validated the behavior in the following platforms - [x] Android - [ ] Windows - [ ] iOS - [ ] Mac ### Issues Fixed Fixes #37440 ### Output ScreenShot |Before|After| |--|--| | <img width="363" height="657" alt="image" src="https://github.com/user-attachments/assets/3dc925f8-5621-44d7-95ea-39b9e3bdd19b" /> | <img width="363" height="657" alt="image" src="https://github.com/user-attachments/assets/e085a680-f78c-4ce3-8f83-351569155f74" /> |
<!-- 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 `ShadowTypeConverter` constructs a runtime `Regex` whenever it parses a shadow string. That reference contributes to retaining `System.Text.RegularExpressions` and additional regex implementation code in trimmed MAUI Android apps. ### Broader goal and related work This PR is one step toward removing the roughly 300 KB linked `System.Text.RegularExpressions` assembly from MAUI apps that do not use regular expressions in their own application logic. Removing the `ShadowTypeConverter` root is not sufficient by itself because other framework and dependency roots still retain regex code. Related work toward that goal includes: - #38616 trims disabled MAUI Aspire support, including `Microsoft.Maui`'s source-generated `LocalhostRegex`, when the Aspire feature switch is off. - dotnet/android#12813 avoids unnecessary XML marshalling references in trimmable type-map dispatch assemblies. This helps remove XML assemblies where they are not otherwise needed; `System.Private.Xml` contains a generated `LanguageRegex` implementation that can independently retain regex code. Additional roots may still need to be removed or made trimmable before `System.Text.RegularExpressions` disappears entirely from a given app. For example, the measured sample-content app also reaches regex through `CommunityToolkit.Maui`, `System.Data.Common`, and `System.Private.Xml`. ### Description of Change Replaces the runtime `Regex` with an allocation-conscious inline tokenizer/parser. The parser intentionally preserves the existing unanchored `Regex.Matches` behavior, including supported color forms, invariant-culture decimal/scientific numbers, Unicode whitespace, ignored punctuation, greedy 3-to-8 digit hex matching, and rollback for incomplete decimals or exponents. Token boundaries are stored in a stack-allocated `Span<Part>`, and only matched tokens are materialized as strings for the existing color and numeric parsers. The project now also bans the `System.Text.RegularExpressions` namespace through a `Controls.Core`-specific `BannedSymbols.txt`, preventing this dependency from being reintroduced. ### Performance considerations Vectorizing the character scans was considered but intentionally not implemented. Shadow strings are normally short (roughly tens of characters) and whitespace runs are generally zero to two characters, so SIMD setup and branching are unlikely to beat the straightforward scalar loops. A vectorized path would also require separate `netstandard` fallbacks and careful tables to preserve the old regex's Unicode `\s` and `\d` behavior, adding disproportionate complexity without demonstrated benefit. ### Tests - Added focused coverage for every supported color syntax, offsets/radius/opacity, whitespace, malformed values, invariant culture, and legacy regex edge cases. - `ShadowTests`: 85 passed. - `Controls.Core` builds for `netstandard2.0`, `netstandard2.1`, and `net10.0`. - Verified an intentional `System.Text.RegularExpressions.Regex` usage in `Controls.Core` fails with RS0030. ### Android size measurement Published identical stock `.NET 11 preview 7` `dotnet new maui --sample-content` apps in Release with `TrimMode=partial`, replacing only the `Microsoft.Maui.Controls.dll` input in the patched build. | Artifact | Baseline | Patched | Delta | |---|---:|---:|---:| | Signed APK | 36,903,788 B | 36,899,692 B | **-4,096 B** | | Unsigned APK | 36,774,978 B | 36,771,221 B | **-3,757 B** | | Linked `Microsoft.Maui.Controls.dll` (per ABI) | 1,495,552 B | 1,495,040 B | **-512 B** | | Linked `System.Text.RegularExpressions.dll` (per ABI) | 334,336 B | 330,752 B | **-3,584 B** | | arm64 assembly store | 7,689,840 B | 7,688,216 B | **-1,624 B** | | x64 assembly store | 7,899,160 B | 7,896,448 B | **-2,712 B** | `System.Text.RegularExpressions` remains retained by other roots in this sample: `CommunityToolkit.Maui`, `Microsoft.Maui` (`LocalhostRegex`), `System.Data.Common`, and `System.Private.Xml`. This change removes the `Microsoft.Maui.Controls` reference and reduces the linked regex implementation, but does not eliminate the assembly from this app. ### Issues Fixed None. --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…38665) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ### Description of Change Fix the two Android API 36 / Pixel 3 XL SafeAreaEdges failures in [build 1602666](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1602666&view=logs&j=217a4b68-6397-5ebe-0d4b-1177e8401828&t=3a87bec2-0591-537a-1f29-40eb70176265). - Preserve the full top inset throughout a full-height page's navigation transition, including `0 < viewTop <= topInset`. Check animation before partial overlap, and preserve the translated-child height guard from #38295. - Replace catch-and-retry NUnit assertions in `SafeAreaNoWhiteSpaceAfterKeyboardDismissAndEdgeToggle` with delayed constraints. NUnit 4.0.1 records an assertion failure before throwing, so catching it and succeeding on a later attempt still leaves the test failed. The original CI device log actually shows the grid shrinking from 2705 to 1613 pixels and returning to 2705 after dismissal. - Preserve the 15-second polling window, 500-ms interval, keyboard visibility checks, and one-pixel restoration tolerance. Check restored height and Y together on the same rectangle. - Add six Android native cases exercising the production inset helper: full-height offsets 0, 1, 99, 100, and 101 with a 100-pixel top inset, plus a translated short child. Assert padding and inset consumption. No snapshots, screenshot tolerances, public APIs, dependencies, or CI configuration are changed. `LayoutShouldBeCorrectOnFirstNavigation` remains unchanged. ### Regression origins | Failure | Introducing change | Evidence | | --- | --- | --- | | Persistent incorrect top inset during navigation | #33788, commit `9c0887b8c343a1a98762acfccb64190355e175ee` | Removed the deferred inset reapplication added in #33285 and introduced `viewTop > top`, leaving the final `0 < viewTop <= top` transition range unprotected. | | Transient keyboard measurements retained as NUnit failures | #31022, commit `0371d318282cc6f0cbb96d36315e7fc2f70680ff` | Introduced catch-and-retry `RetryAssert` while the Android UI project already referenced NUnit 4.0.1. | | The specific keyboard test exposing that defect | #35083 | Added `SafeAreaNoWhiteSpaceAfterKeyboardDismissAndEdgeToggle` using that helper. The later keyboard waits in #37741 did not isolate recorded NUnit failures. | These are source-history attributions, not a historical full-build bisect. The keyboard failure is a test-harness defect, not proof that the grid never resized. ### Validation Tested commit: `8aa80ab8d9312be1aeddfbb200ff580e5c678598`. Environment: dedicated Android API 36 / Pixel 3 XL ARM64 emulator, 1440x2960 at density 560, Release HostApp, existing NUnit 4.0.1 / adapter 4.5.0. Actual TRX and xUnit XML results were inspected, not inferred from process exit codes. | Coverage | Result | | --- | --- | | `SafeAreaNoWhiteSpaceAfterKeyboardDismissAndEdgeToggle` | Passed in **3 consecutive focused runs**, on the first attempt each time. | | `LayoutShouldBeCorrectOnFirstNavigation` | Passed in **3 consecutive focused runs**, on the first attempt each time, against the unchanged snapshot and tolerance. | | Six native inset boundary cases, without native fix | Three expected failures: offsets 1, 99, and 100 produced padding 99, 1, and 0 instead of 100. Settled-origin, offset-101, and translated-child controls passed. | | Same six native cases, with native fix | **6 passed, 0 failed**. | | Complete `Issue28986_ContentPage` fixture, final with-fix A/B leg | **5 passed, 0 failed**, first attempt. | | Standalone NUnit 4.0.1 probe | All five expected outcomes confirmed: caught assertions remain failed; delayed height and compound bounds constraints recover; permanently incorrect height or bounds still fail. | The repository `verify-tests-fail.ps1` finished with **`VERIFICATION PASSED`**, using frozen base `49b62062536b4a2b957d965f76035eb56806615c` and restoring only the two fix files. The final native A/B evidence is deterministic. The without-fix keyboard fixture was timing-dependent and also encountered element-lookup failures; its logs contain the original retained `2705` assertion. The standalone NUnit probe independently isolates that bookkeeping defect. No claim is made that every broad-fixture failure was caused by this PR's targeted bug. Initial verification attempts were blocked by the pinned XHarness runtime and its default instrumentation selection. They are not counted as native proof. Final native execution used the manifest's explicit `com.microsoft.maui.core.devicetests.TestInstrumentation` with a session-local runtime. No repository tool versions or machine-wide SDKs were changed. Focused UI command, executed three times: ```powershell pwsh .github/scripts/BuildAndRunHostApp.ps1 -Platform android -Configuration Release -DeviceUdid emulator-5554 -TestFilter 'FullyQualifiedName~Issue33038|FullyQualifiedName~SafeAreaNoWhiteSpaceAfterKeyboardDismissAndEdgeToggle' ``` The worktree was clean after verification. PR CI is separate: [maui-pr build 1602977](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1602977) is running; this is not a full-CI-green or full-suite-green claim. No `maui-pr-uitests` build had been scheduled at the time of this update. ### Related work and constraints The native correction follows the narrowly scoped approach proposed in closed, unmerged #38641, without its unrelated MacCatalyst skip. Open #37953 proposes a broader SafeArea redesign; this PR keeps a small correction and fixes the separate NUnit bookkeeping defect. Do not replace the navigation baseline, widen its tolerance, or remove the translated-child guard to make the test pass. Do not use caught NUnit assertions as a polling predicate. The generic Appium helper remains unchanged here to avoid adding an NUnit dependency or broad test-infrastructure changes. ### Issues Fixed Fixes #37555 Fixes #37556 Refs #33038 Refs #38135 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…nect (#38653) <!-- 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 Details When a CollectionView has an EmptyView, MAUI posts a layout callback to size it. If the handler is disconnected before that callback runs, the code still tries to access PlatformView. it crashes the application. ### Root Cause Android queues the empty-view layout work to run during the next UI-loop cycle. Meanwhile, navigation can disconnect the handler and clear its PlatformView. The queued callback later reads PlatformView, causing the “PlatformView cannot be null here” exception. ### Description of Change The native RecyclerView is saved before scheduling the delayed empty-view layout update, so the callback does not access the handler after it disconnects. The callback safely uses this saved view to find the empty-view item and request a new layout, preventing the PlatformView cannot be null here crash. Validated the behavior in the following platforms - [x] Android - [ ] Windows - [ ] iOS - [ ] Mac ### Issues Fixed Fixes #38526 ### Output ScreenShot |Before|After| |--|--| | <video src="https://github.com/user-attachments/assets/b61c5b9c-cb57-400d-9f82-64bb08a68b4f" >| <video src="https://github.com/user-attachments/assets/fa9e3ab3-cd52-4eca-8966-489f5d753613">| --------- Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…#38651) <!-- 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 Details label?.SetBinding(...) should create a compiled binding when label is not null. Instead, MAUI did not generate the required interceptor, so the app compiled but threw Call to SetBinding<...> was not intercepted at runtime. ### Root Cause label.SetBinding(...) and label?.SetBinding(...) have different C# syntax-tree shapes. The MAUI generator recognized only the ordinary call shape, so it skipped null-conditional calls and did not generate an interceptor. ### Description of Change GetInvokedMethodName now recognizes both syntax types. Therefore, ordinary and null-conditional SetBinding calls follow the same interceptor-generation process. Validated the behavior in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Issues Fixed Fixes #38365 ### Output ScreenShot |Before|After| |--|--| | <video src="https://github.com/user-attachments/assets/0c5a735d-4a06-4261-8488-f19f464a2be9" >| <video src="https://github.com/user-attachments/assets/b700be4b-776f-4def-bbd2-8325d1007bd1">|
…s not reactive at runtime (#38551) <!-- 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! ### RootCause: In `GesturePlatformManager.iOS.cs`, the native `UITapGestureRecognizer` is created once in `CreateTapRecognizer` with the `NumberOfTapsRequired` value snapshotted at creation time. The PropertyChanged handler OnTapGestureRecognizerPropertyChanged only reacted to TapGestureRecognizer.ButtonsProperty changes (triggering LoadRecognizers()), so changing NumberOfTapsRequired at runtime never propagated to the native recognizer. (Android already reads NumberOfTapsRequired dynamically on each tap via a predicate filter, so it wasn't affected.) ### Fix Description: Mirrored the existing `OnSwipeGestureRecognizerPropertyChanged` pattern — when NumberOfTapsRequiredProperty changes, look up the already-created native `UITapGestureRecognizer` instances in `_gestureRecognizers` and update NumberOfTapsRequired directly, since UIKit allows changing this property on a live recognizer. ### Issues Fixed Fixes #38291 ### Tested the behaviour in the following platforms - [ ] Android - [ ] 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/24f29bdd-e499-474a-9f38-adf317cb3add">|<video width="100" height="100" alt="After Fix" src="https://github.com/user-attachments/assets/c8d078fb-c5c4-4762-a559-5f8c885bfb52">|
Contributor
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 38779Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 38779" |
|
Azure Pipelines: Successfully started running 1 pipeline(s). There may be pipelines that require an authorized user to comment /azp run to run. |
Contributor
Author
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!
SR12 candidate snapshot
Draft candidate for .NET MAUI 10 SR12 (10.0.120), following the 10.0.110 SR11 release. Tracks #38457.
inflight/currentat1aa4552fc784d4b443c5126c47ba4626712020fd.main, captured at3d7ff41c8e9ee0e23c48df72b346218cb0071dd7.kubaflo-sr12-candidate. Unlike prior candidate August 10th, Candidate #37393 (inflight/candidate->main), this PR uses an isolated, frozen feature branch. It does not create or modifyinflight/candidate,inflight/current, or any release ref.eng/Versions.propsretainsPatchVersion=120, the existingci.main/ conditionalci.inflightprerelease labels, andStabilizePackageVersion=falseby default. This is not a stabilization or final-package-version change.Required ordering
Keep this PR in draft until the candidate has been reviewed and validated. Cut the SR12 release branch from the approved candidate/main while PatchVersion is still 120. The next-cycle version bump #38778 must merge only after that SR12 branch cut.
Validation status
The snapshot SHA, captured base ancestry, commit delta, preserved version settings, and published branch SHA have been checked. CI for this newly created candidate PR is not yet validated. No successful build/test outcome or ship-readiness claim is made by this PR; further candidate review and validation are required.