Skip to content

[iOS,MacCatalyst] Fix for SwipeView.Open() throwing an ArgumentException on the second programmatic call#34982

Merged
kubaflo merged 2 commits into
dotnet:inflight/currentfrom
BagavathiPerumal:fix-34917
Apr 16, 2026
Merged

[iOS,MacCatalyst] Fix for SwipeView.Open() throwing an ArgumentException on the second programmatic call#34982
kubaflo merged 2 commits into
dotnet:inflight/currentfrom
BagavathiPerumal:fix-34917

Conversation

@BagavathiPerumal
Copy link
Copy Markdown
Contributor

@BagavathiPerumal BagavathiPerumal commented Apr 15, 2026

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!

Issue Details

The issue occurs when calling the SwipeView.Open() method programmatically multiple times on iOS and MacCatalyst platforms. The first call to open swipe items (such as RightItems or BottomItems) works as expected, but the second call throws a System.ArgumentException with the message “An item with the same key has already been added.”

This behavior is specific to certain swipe directions that rely on negative offsets (such as right and bottom swipe actions), where the swipe interaction briefly appears and then resets unexpectedly. As a result, internal state inconsistencies lead to a crash during subsequent calls.

Root Cause

The issue occur because of an incorrect use of Math.Abs on the _swipeOffset value inside the ProgrammaticallyOpenSwipeItem()method. This operation removes the negative sign required for specific swipe directions (such as left or up), causing the offset to become invalid during layout validation.

Due to this invalid offset, the swipe view resets to a closed state while still retaining previously added entries in the _swipeItems dictionary. When Open() is called again, the same keys are added again to the dictionary, resulting in a duplicate key exception.

Description of Change

The fix involves removing the Math.Abs operation on _swipeOffset to preserve the correct directional value required for swipe behavior, ensuring that the swipe state remains consistent after layout validation.

Additionally, a defensive improvement is introduced by clearing the _swipeItems dictionary before repopulating it in the UpdateSwipeItems() method. This prevents duplicate key insertion and ensures that the method behaves safely even if invoked multiple times under unexpected conditions.

Issues Fixed

Fixes #34917

Validated the behaviour in the following platforms

  • Windows
  • Android
  • iOS
  • Mac

Output

Before After
34917-BeforeFix.mov
34917-AfterFix.mov

…ption on the second programmatic call for RightItems/BottomItems on iOS/Mac Catalyst.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 15, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34982

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34982"

@dotnet-policy-service dotnet-policy-service Bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Apr 15, 2026
@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Apr 15, 2026

🚦 Gate — Test Before and After Fix

👋 @BagavathiPerumal — new gate results are available. Please review the latest session below.

🚦 Gate Sessione905502 · fix-34917: Made code changes to fix the SwipeView.Open() ArgumentException on the second programmatic call for RightItems/BottomItems on iOS/Mac Catalyst. · 2026-04-15 20:05 UTC

Gate Result: ✅ PASSED

Platform: IOS · Base: main · Merge base: eb0b82fe

Test Without Fix (expect FAIL) With Fix (expect PASS)
🖥️ Issue34917 Issue34917 ✅ FAIL — 224s ✅ PASS — 97s
🔴 Without fix — 🖥️ Issue34917: FAIL ✅ · 224s
  Determining projects to restore...
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 557 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 654 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 12.14 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/Foldable/src/Controls.Foldable.csproj (in 15.53 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Xaml/Controls.Xaml.csproj (in 15.54 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 15.55 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/Maps/src/Controls.Maps.csproj (in 15.56 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj (in 15.56 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj (in 15.58 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 15.56 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Core/maps/src/Maps.csproj (in 15.58 sec).
/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0-ios26.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0-ios26.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0-ios26.0/Microsoft.Maui.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Maps.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  Controls.Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Maps.dll
  Microsoft.AspNetCore.Components.WebView.Maui -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-ios26.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
  Controls.Foldable -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Foldable.dll
  Controls.Xaml -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Xaml.dll
  Detected signing identity:
    Code Signing Key: "" (-)
    Provisioning Profile: "" () - no entitlements
    Bundle Id: com.microsoft.maui.uitests
    App Id: com.microsoft.maui.uitests
  Controls.TestCases.HostApp -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-ios/iossimulator-arm64/Controls.TestCases.HostApp.dll
  Optimizing assemblies for size may change the behavior of the app. Be sure to test after publishing. See: https://aka.ms/dotnet-illink
  Optimizing assemblies for size. This process might take a while.

Build succeeded.

/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
    1 Warning(s)
    0 Error(s)

Time Elapsed 00:01:41.78
  Determining projects to restore...
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.Core/UITest.Core.csproj (in 666 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 672 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/tests/CustomAttributes/Controls.CustomAttributes.csproj (in 667 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 676 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/VisualTestUtils/VisualTestUtils.csproj (in 0.9 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 693 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 745 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 360 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.NUnit/UITest.NUnit.csproj (in 1.46 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.Appium/UITest.Appium.csproj (in 2.73 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.Analyzers/UITest.Analyzers.csproj (in 3.94 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/VisualTestUtils.MagickNet/VisualTestUtils.MagickNet.csproj (in 7.88 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.iOS.Tests/Controls.TestCases.iOS.Tests.csproj (in 7.9 sec).
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  Controls.CustomAttributes -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
  Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  UITest.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
  VisualTestUtils -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
  UITest.NUnit -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
  UITest.Appium -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
  VisualTestUtils.MagickNet -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
  UITest.Analyzers -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
  Controls.TestCases.iOS.Tests -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
Test run for /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (arm64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
/Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.04]   Discovering: Controls.TestCases.iOS.Tests
[xUnit.net 00:00:00.13]   Discovered:  Controls.TestCases.iOS.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
   NUnit3TestExecutor discovered 2 of 2 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 4/15/2026 1:03:55 PM FixtureSetup for Issue34917(iOS)
>>>>> 4/15/2026 1:04:00 PM SwipeViewOpenBottomDoesNotThrowOnSecondCall Start
>>>>> 4/15/2026 1:04:02 PM SwipeViewOpenBottomDoesNotThrowOnSecondCall Stop
>>>>> 4/15/2026 1:04:02 PM Log types: syslog, crashlog, performance, safariConsole, safariNetwork, server
  Failed SwipeViewOpenBottomDoesNotThrowOnSecondCall [2 s]
  Error Message:
     Second consecutive Open(BottomItems) call should not throw an exception.
Assert.That(App.FindElement(StatusLabelId).GetText(), Is.EqualTo("Success"))
  Expected string length 7 but was 24. Strings differ at index 0.
  Expected: "Success"
  But was:  "Error: ArgumentException"
  -----------^

  Stack Trace:
     at Microsoft.Maui.TestCases.Tests.Issues.Issue34917.SwipeViewOpenBottomDoesNotThrowOnSecondCall() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34917.cs:line 43

1)    at Microsoft.Maui.TestCases.Tests.Issues.Issue34917.SwipeViewOpenBottomDoesNotThrowOnSecondCall() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34917.cs:line 43


>>>>> 4/15/2026 1:04:02 PM SwipeViewOpenRightDoesNotThrowOnSecondCall Start
>>>>> 4/15/2026 1:04:04 PM SwipeViewOpenRightDoesNotThrowOnSecondCall Stop
>>>>> 4/15/2026 1:04:04 PM Log types: syslog, crashlog, performance, safariConsole, safariNetwork, server
  Failed SwipeViewOpenRightDoesNotThrowOnSecondCall [1 s]
  Error Message:
     Second consecutive Open(RightItems) call should not throw an exception.
Assert.That(App.FindElement(StatusLabelId).GetText(), Is.EqualTo("Success"))
  Expected string length 7 but was 24. Strings differ at index 0.
  Expected: "Success"
  But was:  "Error: ArgumentException"
  -----------^

  Stack Trace:
     at Microsoft.Maui.TestCases.Tests.Issues.Issue34917.SwipeViewOpenRightDoesNotThrowOnSecondCall() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34917.cs:line 25

1)    at Microsoft.Maui.TestCases.Tests.Issues.Issue34917.SwipeViewOpenRightDoesNotThrowOnSecondCall() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34917.cs:line 25


NUnit Adapter 4.5.0.0: Test execution complete

Total tests: 2
     Failed: 2
Test Run Failed.
 Total time: 1.0706 Minutes

🟢 With fix — 🖥️ Issue34917: PASS ✅ · 97s
  Determining projects to restore...
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 395 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 407 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 413 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 441 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 453 ms).
  6 of 11 projects are up-to-date for restore.
/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0-ios26.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0-ios26.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0-ios26.0/Microsoft.Maui.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Maps.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  Controls.Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Maps.dll
  Controls.Xaml -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Xaml.dll
  Controls.Foldable -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Foldable.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  Microsoft.AspNetCore.Components.WebView.Maui -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-ios26.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
  Detected signing identity:
    Code Signing Key: "" (-)
    Provisioning Profile: "" () - no entitlements
    Bundle Id: com.microsoft.maui.uitests
    App Id: com.microsoft.maui.uitests
  Controls.TestCases.HostApp -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-ios/iossimulator-arm64/Controls.TestCases.HostApp.dll
  Optimizing assemblies for size may change the behavior of the app. Be sure to test after publishing. See: https://aka.ms/dotnet-illink
  Optimizing assemblies for size. This process might take a while.

Build succeeded.

/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
    1 Warning(s)
    0 Error(s)

Time Elapsed 00:00:48.18
  Determining projects to restore...
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 333 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 388 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 384 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 396 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 419 ms).
  8 of 13 projects are up-to-date for restore.
  Controls.CustomAttributes -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
  Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  VisualTestUtils -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
  UITest.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
  VisualTestUtils.MagickNet -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
  UITest.NUnit -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
  UITest.Appium -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
  UITest.Analyzers -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
  Controls.TestCases.iOS.Tests -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
Test run for /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (arm64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
/Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.05]   Discovering: Controls.TestCases.iOS.Tests
[xUnit.net 00:00:00.17]   Discovered:  Controls.TestCases.iOS.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
   NUnit3TestExecutor discovered 2 of 2 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 4/15/2026 1:05:32 PM FixtureSetup for Issue34917(iOS)
>>>>> 4/15/2026 1:05:37 PM SwipeViewOpenBottomDoesNotThrowOnSecondCall Start
>>>>> 4/15/2026 1:05:39 PM SwipeViewOpenBottomDoesNotThrowOnSecondCall Stop
  Passed SwipeViewOpenBottomDoesNotThrowOnSecondCall [2 s]
>>>>> 4/15/2026 1:05:39 PM SwipeViewOpenRightDoesNotThrowOnSecondCall Start
>>>>> 4/15/2026 1:05:41 PM SwipeViewOpenRightDoesNotThrowOnSecondCall Stop
  Passed SwipeViewOpenRightDoesNotThrowOnSecondCall [1 s]
NUnit Adapter 4.5.0.0: Test execution complete

Test Run Successful.
Total tests: 2
     Passed: 2
 Total time: 21.7441 Seconds

📁 Fix files reverted (1 files)
  • src/Core/src/Platform/iOS/MauiSwipeView.cs

@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Apr 15, 2026

🤖 AI Summary

👋 @BagavathiPerumal — new AI review results are available. Please review the latest session below.

📊 Review Sessione905502 · fix-34917: Made code changes to fix the SwipeView.Open() ArgumentException on the second programmatic call for RightItems/BottomItems on iOS/Mac Catalyst. · 2026-04-15 20:46 UTC
🔍 Pre-Flight — Context & Validation

Issue: #34917 - [net 11.0][iOS,MacCatalyst] SwipeView.Open() throws ArgumentException on second programmatic call
PR: #34982 - [iOS,MacCatalyst] Fix for SwipeView.Open() throwing an ArgumentException on the second programmatic call
Platforms Affected: iOS, MacCatalyst
Files Changed: 1 implementation, 2 test

Key Findings

  • Root cause: ProgrammaticallyOpenSwipeItem called Math.Abs(_swipeOffset) after Swipe(animated), stripping the negative sign required for Left/Up swipe directions (RightItems → Left direction, BottomItems → Up direction)
  • This caused _swipeOffset to become positive for directions requiring a negative offset, making layout validation fail and forcing the swipe view to reset to closed state
  • When closed, DisposeSwipeItems() clears the dictionary, BUT the reset was likely happening asynchronously (animated) or at certain timings that left _swipeItems still populated
  • On the second call to Open(), UpdateSwipeItems() would try to add the same ISwipeItem keys again, throwing ArgumentException: An item with the same key has already been added
  • Fix 1: Remove _swipeOffset = Math.Abs(_swipeOffset) from ProgrammaticallyOpenSwipeItem — this is the primary fix addressing the root cause
  • Fix 2: Add _swipeItems.Clear() at start of UpdateSwipeItems() — defensive measure that also handles edge cases where the dictionary might still have stale entries
  • The fix is iOS/MacCatalyst-specific (MauiSwipeView.cs is in Platform/iOS/)
  • Tests use UITest framework with Appium; test page catches exceptions and shows "Success" or "Error: ExceptionType"

Code Review Summary

Verdict: LGTM
Confidence: High
Errors: 0 | Warnings: 0 | Suggestions: 1

Key code review findings:

  • 💡 src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34917.cs — Consider adding an Open→Close→Reopen test to cover the DisposeSwipeItems path (not a blocker)
  • No errors or warnings found; both implementation changes are sound and necessary

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #34982 (1) Remove Math.Abs(_swipeOffset) in ProgrammaticallyOpenSwipeItem; (2) Add _swipeItems.Clear() in UpdateSwipeItems ✅ PASSED (Gate) MauiSwipeView.cs Original PR

🔬 Code Review — Deep Analysis

Code Review — PR #34982

Independent Assessment

What this changes:

  1. MauiSwipeView.cs: Adds _swipeItems.Clear() at the start of UpdateSwipeItems(), and removes _swipeOffset = Math.Abs(_swipeOffset) from the end of ProgrammaticallyOpenSwipeItem().
  2. Two new test files adding a UI test page and the corresponding NUnit test class for the SwipeView open scenario.

Inferred motivation (from code alone):
UpdateSwipeItems() calls _swipeItems.Add(item, swipeItem) for each swipe item. Dictionary.Add() throws ArgumentException on duplicate keys. If _swipeItems somehow retained stale entries between calls, the second UpdateSwipeItems would crash.

Tracing _swipeOffset = Math.Abs(_swipeOffset) at the end of ProgrammaticallyOpenSwipeItem: after UpdateOffset() sets _swipeOffset to -swipeThreshold for Left/Up directions, Math.Abs makes it positive. Then, on the next LayoutSubviews → Swipe(false) call, ValidateSwipeOffset has this guard for SwipeDirection.Left:

case SwipeDirection.Left:
    if (offset > 0)
        offset = 0;   // positive offset clamped to zero!

This silently resets _isOpen = (0 != 0) = false, without calling DisposeSwipeItems(), leaving _swipeItems populated but _isOpen falsely reporting closed. On the second ProgrammaticallyOpenSwipeItem call, the _isOpen == false guard does not return early, UpdateSwipeItems() runs again, and _swipeItems.Add throws on duplicate keys. This is the exact crash chain.

Is the approach sound?
Yes. Both changes are necessary and complementary:

  • Removing Math.Abs is the root cause fix: preserves the correct signed offset so ValidateSwipeOffset produces the expected non-zero result, keeping _isOpen = true stable across layout passes.
  • Adding _swipeItems.Clear() is the defensive fix: guards against any future path that reaches UpdateSwipeItems() without having cleared the dictionary first. The existing manual-swipe path (ProcessTouchMove) already calls ResetSwipeToInitialPosition → DisposeSwipeItems → _swipeItems.Clear() before UpdateSwipeItems(), so this adds no behavioral change for that path.

Reconciliation with PR Narrative

Author claims: Math.Abs corrupts the negative offset required for Left/Up swipe directions, causing ValidateSwipeOffset to clamp to zero, which resets _isOpen without clearing _swipeItems, leading to duplicate keys on the second call.

Agreement: Complete agreement. The chain I traced independently matches the PR description exactly. The description is precise and technically correct.

One note: The PR author and the issue reporter are the same GitHub user (BagavathiPerumal). The PR is also in draft state, so this review is pre-merge feedback.


Findings

💡 Suggestion — Consider adding a Close → Reopen test to guard adjacent scenario

SwipeViewOpenRightDoesNotThrowOnSecondCall tests two consecutive Opens without closing (the direct bug scenario). A complementary test covering Open → Close → Open would guard the adjacent path where DisposeSwipeItems runs between calls — particularly valuable since this file now lives next to the SwipeView regression history. The Close → Reopen path uses different code: _isOpen == false AND _swipeItems is freshly cleared, which is the "happy path" that the bug indirectly masked.

This isn't a blocker — the reported bug is correctly covered — but it closes a gap in scenario coverage that the regression history for this component warrants.


Devil's Advocate

Challenge: Is _swipeItems.Clear() hiding a deeper problem?
If _swipeItems has stale entries when UpdateSwipeItems is called (outside the Math.Abs bug path), it means a caller didn't go through DisposeSwipeItems. The Clear() fixes the symptom but lets the caller off the hook. However, examining all call sites: the only two callers are ProcessTouchMove (always calls DisposeSwipeItems first) and ProgrammaticallyOpenSwipeItem (whose bug path is now fixed by the Math.Abs removal). The Clear() is therefore genuinely defensive, not a symptom masker, and its cost is O(n) on a small dictionary.

Challenge: Could removing Math.Abs break anything?
_swipeOffset is read by ValidateSwipeOffset, TouchesEnded (!= 0 check), and HandlePan's != 0 check — none of which care about the sign being forced positive. The signed value is exactly what ValidateSwipeOffset expects. No breakage identified.

Challenge: Are the tests reliable?
The App.Tap(CloseButtonId) at the start of SwipeViewOpenBottomDoesNotThrowOnSecondCall looks odd in isolation, but it's valid test isolation — if SwipeViewOpenRightDoesNotThrowOnSecondCall ran first and left the swipe open, the Close tap resets state before the Bottom test. This is correct defensive test sequencing.

Platform scope: The changed file (src/Core/src/Platform/iOS/MauiSwipeView.cs) compiles for iOS and MacCatalyst only. Android and Windows are unaffected. The PR's platform checklist correctly leaves Windows/Android unchecked. The UI test uses PlatformAffected.iOS | PlatformAffected.macOS on the host page but the NUnit class carries no platform exclusion — it will run on all platforms, which is fine since it tests an exception-free scenario that passes trivially on unaffected platforms.


Blast Radius Assessment

Scope: Changes are limited to ProgrammaticallyOpenSwipeItem and UpdateSwipeItems in MauiSwipeView.cs.

  • Math.Abs removal only affects programmatic open calls (not gesture-driven swipes, which never call ProgrammaticallyOpenSwipeItem)
  • _swipeItems.Clear() runs every time UpdateSwipeItems is called — both programmatic and gesture paths — but since the dictionary is always populated fresh immediately after, the cost is clearing an already-correct dictionary on the gesture path
  • Platform scope: iOS and MacCatalyst only
  • No cross-platform regression risk

Verdict: LGTM

Confidence: High

Summary: The root cause is correctly identified and precisely fixed. Both code changes are necessary: Math.Abs removal is the primary fix (prevents _isOpen from being silently reset), and _swipeItems.Clear() is a sound defensive addition. The tests cover the exact reported scenario, and no regressions to adjacent SwipeView behavior were identified.


🔧 Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix (claude-opus-4.6) Use dictionary indexer instead of in UpdateSwipeItems; add before creating new UIStackView PASS MauiSwipeView.cs (+5/-1) Symptom fix leaves Math.Abs root cause in place
2 try-fix (claude-sonnet-4.6) Remove ONLY PASS MauiSwipeView.cs (+0/-2) Minimal root-cause fix; proves single-line removal is sufficient
3 try-fix (gpt-5.3-codex) In Swipe(), call DisposeSwipeItems() when `!_isOpen && !_isSwiping && !_isResettingSwipe && _swipeItems.Count > PASS MauiSwipeView.cs (+7/-0) State-consistency fix; more invasive touch point in Swipe() 0`
4 try-fix (gpt-5.4) In ProgrammaticallyOpenSwipeItem, add if (!_isOpen && _swipeItems.Count > 0) ResetSwipe(false) guard before PASS MauiSwipeView.cs (+3/-0) API-boundary guard; broader reset side effects proceeding
PR PR #34982 (1) Remove Math.Abs(_swipeOffset) in ProgrammaticallyOpenSwipeItem; (2) Add _swipeItems.Clear() in UpdateSwipeItems PASSED (Gate) MauiSwipeView.cs Root cause fix + defensive best combination clear

Cross-Pollination

Model Round New Ideas? Details
claude-opus-4.6 2 No "NO NEW design space covered by 5 attempts"

Exhausted: Yes
Selected Fix: PR # Removes the root cause (Math.Abs) AND adds a defensive _swipeItems.Clear() that guards against any future path where UpdateSwipeItems is called with stale entries. Attempt 2 shows the single-line removal is technically sufficient, but the PR's combination is more robust. The Clear() has zero behavioral impact on existing gesture paths (they always go through DisposeSwipeItems first) and costs O(n) on a small dictionary.34982


📋 Report — Final Recommendation

✅ Final Recommendation: APPROVE

Phase Status

Phase Status Notes
Pre-Flight ✅ COMPLETE Issue #34917, iOS/MacCatalyst, 1 impl file + 2 test files
Code Review ✅ LGTM (high confidence) 0 errors, 0 warnings, 1 suggestion (non-blocking)
Gate ✅ PASSED ios — tests FAIL without fix, PASS with fix
Try-Fix ✅ COMPLETE 4 attempts, 4 passing (+ PR); exploration exhausted
Report ✅ COMPLETE

Code Review Impact on Try-Fix

Code review found no errors or warnings — verdict was LGTM with high confidence. With no blocking findings to address, try-fix models were free to explore the full fix design space independently. The one 💡 suggestion (adding an Open→Close→Reopen test) was informational and did not guide any attempt toward a different fix strategy. All 4 models confirmed the fix is sound from different angles, reinforcing the code review's LGTM verdict.

Summary

PR #34982 correctly identifies and fixes a long-standing iOS/MacCatalyst bug where calling SwipeView.Open() programmatically more than once with the same direction throws ArgumentException: An item with the same key has already been added. The fix is minimal, precise, and well-tested. Four independent fix attempts all passed, and all models confirmed no new approaches remained unexplored.

Root Cause

ProgrammaticallyOpenSwipeItem called _swipeOffset = Math.Abs(_swipeOffset) after Swipe(animated). For Left/Up swipe directions (used by RightItems and BottomItems respectively), UpdateOffset correctly sets _swipeOffset to a negative value. Math.Abs then strips the sign, making it positive. On the next layout pass, ValidateSwipeOffset clamps any positive offset to 0 for Left/Up directions — silently setting _isOpen = false — without ever calling DisposeSwipeItems(). On the second Open() call, _swipeItems still has entries from the first call, and UpdateSwipeItems().Add() throws on duplicate keys.

Fix Quality

The PR's two-part fix is the best among all candidates:

  1. Remove Math.Abs(_swipeOffset) — the true root cause fix. Attempt 2 confirmed this single-line removal alone is sufficient to pass all tests. No edge case where keeping it would be correct was identified.

  2. Add _swipeItems.Clear() in UpdateSwipeItems() — a sound defensive addition. The gesture-driven path always calls DisposeSwipeItems (which clears the dictionary) before UpdateSwipeItems, so this Clear() has no behavioral impact on normal gesture flows. It costs O(n) on a small dictionary and guards against any future code path that might reach UpdateSwipeItems without prior cleanup.

Compared to the alternatives found by Try-Fix:

  • Attempt 1 (dictionary indexer): Masks the symptom without fixing the root cause. Math.Abs remains.
  • Attempt 3 (DisposeSwipeItems in Swipe()): Valid but adds side effects (early return from Swipe) at a lower-level touch point.
  • Attempt 4 (ResetSwipe guard in ProgrammaticallyOpenSwipeItem): Valid but ResetSwipe() resets more state (including _swipeThreshold, _swipeDirection) which may have subtler behavioral differences.

The PR's combination is the cleanest: remove the bug (Math.Abs) and add a guard (Clear) exactly where UpdateSwipeItems is populated.

One non-blocking suggestion from code review: Adding an Open→Close→Reopen test would guard the DisposeSwipeItems path between calls. Not required for merge, but worthwhile for completeness given this component's regression history.


@MauiBot MauiBot added s/agent-approved AI agent recommends approval - PR fix is correct and optimal s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Apr 15, 2026
@sheiksyedm sheiksyedm marked this pull request as ready for review April 16, 2026 05:44
Copilot AI review requested due to automatic review settings April 16, 2026 05:44
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes an iOS/MacCatalyst SwipeView regression where calling SwipeView.Open() programmatically multiple times can throw ArgumentException due to inconsistent swipe offset/state, and adds a UI test to prevent regressions.

Changes:

  • Preserve directional _swipeOffset during programmatic opens by removing an incorrect Math.Abs normalization.
  • Add a defensive _swipeItems.Clear() before repopulating swipe item views during UpdateSwipeItems().
  • Add a new HostApp repro page and corresponding Appium/NUnit UI tests for issue #34917.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/Core/src/Platform/iOS/MauiSwipeView.cs Fixes programmatic open offset sign handling and defensively resets swipe item mapping before rebuilding.
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34917.cs Adds UI tests verifying repeated programmatic Open() calls don’t throw for Right/Bottom items.
src/Controls/tests/TestCases.HostApp/Issues/Issue34917.cs Adds a HostApp issue page with buttons that reproduce the repeated Open() scenario and report success/failure via a label.
Comments suppressed due to low confidence (1)

src/Core/src/Platform/iOS/MauiSwipeView.cs:320

  • UpdateSwipeItems() clears _swipeItems, but it still unconditionally creates a new _actionView and calls AddSubview(_actionView) without removing any existing action view. If UpdateSwipeItems gets invoked multiple times without DisposeSwipeItems/ResetSwipe (which this change is trying to tolerate), old action views can be left in the view hierarchy and overlap/consume memory. Consider removing the existing _actionView from its superview (and clearing related state) before creating/adding a new one, or route through DisposeSwipeItems when rebuilding.
			_swipeItemsRect = new List<CGRect>();
			_swipeItems.Clear();

			double swipeItemsWidth;

			if (_swipeDirection == SwipeDirection.Left || _swipeDirection == SwipeDirection.Right)
				swipeItemsWidth = items.Count * SwipeViewExtensions.SwipeItemWidth;
			else
				swipeItemsWidth = _contentView.Frame.Width;

			_actionView = new UIStackView
			{
				Axis = UILayoutConstraintAxis.Horizontal,
				Frame = new CGRect(0, 0, swipeItemsWidth, _contentView.Frame.Height)
			};

			foreach (var item in items)
			{
				UIView swipeItem = item.ToPlatform(Element.Handler.MauiContext);
				_actionView.AddSubview(swipeItem);
				_swipeItems.Add(item, swipeItem);
			}

			AddSubview(_actionView);

@sheiksyedm
Copy link
Copy Markdown
Contributor

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

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 2 pipeline(s).

@kubaflo kubaflo changed the base branch from main to inflight/current April 16, 2026 10:28
@kubaflo kubaflo merged commit faa1a6d into dotnet:inflight/current Apr 16, 2026
124 of 163 checks passed
devanathan-vaithiyanathan pushed a commit to Tamilarasan-Paranthaman/maui that referenced this pull request Apr 21, 2026
…ion on the second programmatic call (dotnet#34982)

<!-- 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 issue occurs when calling the SwipeView.Open() method
programmatically multiple times on iOS and MacCatalyst platforms. The
first call to open swipe items (such as RightItems or BottomItems) works
as expected, but the second call throws a System.ArgumentException with
the message “An item with the same key has already been added.”
 
This behavior is specific to certain swipe directions that rely on
negative offsets (such as right and bottom swipe actions), where the
swipe interaction briefly appears and then resets unexpectedly. As a
result, internal state inconsistencies lead to a crash during subsequent
calls.

### Root Cause

The issue occur because of an incorrect use of Math.Abs on the
_swipeOffset value inside the ProgrammaticallyOpenSwipeItem()method.
This operation removes the negative sign required for specific swipe
directions (such as left or up), causing the offset to become invalid
during layout validation.
 
Due to this invalid offset, the swipe view resets to a closed state
while still retaining previously added entries in the _swipeItems
dictionary. When Open() is called again, the same keys are added again
to the dictionary, resulting in a duplicate key exception.

### Description of Change

The fix involves removing the Math.Abs operation on _swipeOffset to
preserve the correct directional value required for swipe behavior,
ensuring that the swipe state remains consistent after layout
validation.
 
Additionally, a defensive improvement is introduced by clearing the
_swipeItems dictionary before repopulating it in the UpdateSwipeItems()
method. This prevents duplicate key insertion and ensures that the
method behaves safely even if invoked multiple times under unexpected
conditions.

### Issues Fixed
Fixes dotnet#34917

### Validated the behaviour in the following platforms

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

### Output
| Before | After |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/55a131cb-6ccc-4776-80d7-90655651565d">
| <video
src="https://github.com/user-attachments/assets/5efc010e-04ec-4e4d-8729-d43f41d2d6bf">
|
PureWeen pushed a commit that referenced this pull request Apr 22, 2026
…ion on the second programmatic call (#34982)

<!-- 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 issue occurs when calling the SwipeView.Open() method
programmatically multiple times on iOS and MacCatalyst platforms. The
first call to open swipe items (such as RightItems or BottomItems) works
as expected, but the second call throws a System.ArgumentException with
the message “An item with the same key has already been added.”
 
This behavior is specific to certain swipe directions that rely on
negative offsets (such as right and bottom swipe actions), where the
swipe interaction briefly appears and then resets unexpectedly. As a
result, internal state inconsistencies lead to a crash during subsequent
calls.

### Root Cause

The issue occur because of an incorrect use of Math.Abs on the
_swipeOffset value inside the ProgrammaticallyOpenSwipeItem()method.
This operation removes the negative sign required for specific swipe
directions (such as left or up), causing the offset to become invalid
during layout validation.
 
Due to this invalid offset, the swipe view resets to a closed state
while still retaining previously added entries in the _swipeItems
dictionary. When Open() is called again, the same keys are added again
to the dictionary, resulting in a duplicate key exception.

### Description of Change

The fix involves removing the Math.Abs operation on _swipeOffset to
preserve the correct directional value required for swipe behavior,
ensuring that the swipe state remains consistent after layout
validation.
 
Additionally, a defensive improvement is introduced by clearing the
_swipeItems dictionary before repopulating it in the UpdateSwipeItems()
method. This prevents duplicate key insertion and ensures that the
method behaves safely even if invoked multiple times under unexpected
conditions.

### Issues Fixed
Fixes #34917

### Validated the behaviour in the following platforms

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

### Output
| Before | After |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/55a131cb-6ccc-4776-80d7-90655651565d">
| <video
src="https://github.com/user-attachments/assets/5efc010e-04ec-4e4d-8729-d43f41d2d6bf">
|
@usman-karatela
Copy link
Copy Markdown

Will this change be available in .NET 10 SR6 or later service releases?

PureWeen pushed a commit that referenced this pull request Apr 28, 2026
…ion on the second programmatic call (#34982)

<!-- 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 issue occurs when calling the SwipeView.Open() method
programmatically multiple times on iOS and MacCatalyst platforms. The
first call to open swipe items (such as RightItems or BottomItems) works
as expected, but the second call throws a System.ArgumentException with
the message “An item with the same key has already been added.”
 
This behavior is specific to certain swipe directions that rely on
negative offsets (such as right and bottom swipe actions), where the
swipe interaction briefly appears and then resets unexpectedly. As a
result, internal state inconsistencies lead to a crash during subsequent
calls.

### Root Cause

The issue occur because of an incorrect use of Math.Abs on the
_swipeOffset value inside the ProgrammaticallyOpenSwipeItem()method.
This operation removes the negative sign required for specific swipe
directions (such as left or up), causing the offset to become invalid
during layout validation.
 
Due to this invalid offset, the swipe view resets to a closed state
while still retaining previously added entries in the _swipeItems
dictionary. When Open() is called again, the same keys are added again
to the dictionary, resulting in a duplicate key exception.

### Description of Change

The fix involves removing the Math.Abs operation on _swipeOffset to
preserve the correct directional value required for swipe behavior,
ensuring that the swipe state remains consistent after layout
validation.
 
Additionally, a defensive improvement is introduced by clearing the
_swipeItems dictionary before repopulating it in the UpdateSwipeItems()
method. This prevents duplicate key insertion and ensures that the
method behaves safely even if invoked multiple times under unexpected
conditions.

### Issues Fixed
Fixes #34917

### Validated the behaviour in the following platforms

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

### Output
| Before | After |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/55a131cb-6ccc-4776-80d7-90655651565d">
| <video
src="https://github.com/user-attachments/assets/5efc010e-04ec-4e4d-8729-d43f41d2d6bf">
|
PureWeen pushed a commit that referenced this pull request Apr 29, 2026
…ion on the second programmatic call (#34982)

<!-- 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 issue occurs when calling the SwipeView.Open() method
programmatically multiple times on iOS and MacCatalyst platforms. The
first call to open swipe items (such as RightItems or BottomItems) works
as expected, but the second call throws a System.ArgumentException with
the message “An item with the same key has already been added.”
 
This behavior is specific to certain swipe directions that rely on
negative offsets (such as right and bottom swipe actions), where the
swipe interaction briefly appears and then resets unexpectedly. As a
result, internal state inconsistencies lead to a crash during subsequent
calls.

### Root Cause

The issue occur because of an incorrect use of Math.Abs on the
_swipeOffset value inside the ProgrammaticallyOpenSwipeItem()method.
This operation removes the negative sign required for specific swipe
directions (such as left or up), causing the offset to become invalid
during layout validation.
 
Due to this invalid offset, the swipe view resets to a closed state
while still retaining previously added entries in the _swipeItems
dictionary. When Open() is called again, the same keys are added again
to the dictionary, resulting in a duplicate key exception.

### Description of Change

The fix involves removing the Math.Abs operation on _swipeOffset to
preserve the correct directional value required for swipe behavior,
ensuring that the swipe state remains consistent after layout
validation.
 
Additionally, a defensive improvement is introduced by clearing the
_swipeItems dictionary before repopulating it in the UpdateSwipeItems()
method. This prevents duplicate key insertion and ensures that the
method behaves safely even if invoked multiple times under unexpected
conditions.

### Issues Fixed
Fixes #34917

### Validated the behaviour in the following platforms

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

### Output
| Before | After |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/55a131cb-6ccc-4776-80d7-90655651565d">
| <video
src="https://github.com/user-attachments/assets/5efc010e-04ec-4e4d-8729-d43f41d2d6bf">
|
github-actions Bot pushed a commit that referenced this pull request May 6, 2026
…ion on the second programmatic call (#34982)

<!-- 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 issue occurs when calling the SwipeView.Open() method
programmatically multiple times on iOS and MacCatalyst platforms. The
first call to open swipe items (such as RightItems or BottomItems) works
as expected, but the second call throws a System.ArgumentException with
the message “An item with the same key has already been added.”
 
This behavior is specific to certain swipe directions that rely on
negative offsets (such as right and bottom swipe actions), where the
swipe interaction briefly appears and then resets unexpectedly. As a
result, internal state inconsistencies lead to a crash during subsequent
calls.

### Root Cause

The issue occur because of an incorrect use of Math.Abs on the
_swipeOffset value inside the ProgrammaticallyOpenSwipeItem()method.
This operation removes the negative sign required for specific swipe
directions (such as left or up), causing the offset to become invalid
during layout validation.
 
Due to this invalid offset, the swipe view resets to a closed state
while still retaining previously added entries in the _swipeItems
dictionary. When Open() is called again, the same keys are added again
to the dictionary, resulting in a duplicate key exception.

### Description of Change

The fix involves removing the Math.Abs operation on _swipeOffset to
preserve the correct directional value required for swipe behavior,
ensuring that the swipe state remains consistent after layout
validation.
 
Additionally, a defensive improvement is introduced by clearing the
_swipeItems dictionary before repopulating it in the UpdateSwipeItems()
method. This prevents duplicate key insertion and ensures that the
method behaves safely even if invoked multiple times under unexpected
conditions.

### Issues Fixed
Fixes #34917

### Validated the behaviour in the following platforms

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

### Output
| Before | After |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/55a131cb-6ccc-4776-80d7-90655651565d">
| <video
src="https://github.com/user-attachments/assets/5efc010e-04ec-4e4d-8729-d43f41d2d6bf">
|
@kubaflo kubaflo added the s/agent-gate-passed AI verified tests catch the bug (fail without fix, pass with fix) label May 20, 2026
github-actions Bot pushed a commit that referenced this pull request May 25, 2026
…ion on the second programmatic call (#34982)

<!-- 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 issue occurs when calling the SwipeView.Open() method
programmatically multiple times on iOS and MacCatalyst platforms. The
first call to open swipe items (such as RightItems or BottomItems) works
as expected, but the second call throws a System.ArgumentException with
the message “An item with the same key has already been added.”
 
This behavior is specific to certain swipe directions that rely on
negative offsets (such as right and bottom swipe actions), where the
swipe interaction briefly appears and then resets unexpectedly. As a
result, internal state inconsistencies lead to a crash during subsequent
calls.

### Root Cause

The issue occur because of an incorrect use of Math.Abs on the
_swipeOffset value inside the ProgrammaticallyOpenSwipeItem()method.
This operation removes the negative sign required for specific swipe
directions (such as left or up), causing the offset to become invalid
during layout validation.
 
Due to this invalid offset, the swipe view resets to a closed state
while still retaining previously added entries in the _swipeItems
dictionary. When Open() is called again, the same keys are added again
to the dictionary, resulting in a duplicate key exception.

### Description of Change

The fix involves removing the Math.Abs operation on _swipeOffset to
preserve the correct directional value required for swipe behavior,
ensuring that the swipe state remains consistent after layout
validation.
 
Additionally, a defensive improvement is introduced by clearing the
_swipeItems dictionary before repopulating it in the UpdateSwipeItems()
method. This prevents duplicate key insertion and ensures that the
method behaves safely even if invoked multiple times under unexpected
conditions.

### Issues Fixed
Fixes #34917

### Validated the behaviour in the following platforms

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

### Output
| Before | After |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/55a131cb-6ccc-4776-80d7-90655651565d">
| <video
src="https://github.com/user-attachments/assets/5efc010e-04ec-4e4d-8729-d43f41d2d6bf">
|
devanathan-vaithiyanathan pushed a commit to devanathan-vaithiyanathan/maui that referenced this pull request Jun 1, 2026
…ion on the second programmatic call (dotnet#34982)

<!-- 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 issue occurs when calling the SwipeView.Open() method
programmatically multiple times on iOS and MacCatalyst platforms. The
first call to open swipe items (such as RightItems or BottomItems) works
as expected, but the second call throws a System.ArgumentException with
the message “An item with the same key has already been added.”
 
This behavior is specific to certain swipe directions that rely on
negative offsets (such as right and bottom swipe actions), where the
swipe interaction briefly appears and then resets unexpectedly. As a
result, internal state inconsistencies lead to a crash during subsequent
calls.

### Root Cause

The issue occur because of an incorrect use of Math.Abs on the
_swipeOffset value inside the ProgrammaticallyOpenSwipeItem()method.
This operation removes the negative sign required for specific swipe
directions (such as left or up), causing the offset to become invalid
during layout validation.
 
Due to this invalid offset, the swipe view resets to a closed state
while still retaining previously added entries in the _swipeItems
dictionary. When Open() is called again, the same keys are added again
to the dictionary, resulting in a duplicate key exception.

### Description of Change

The fix involves removing the Math.Abs operation on _swipeOffset to
preserve the correct directional value required for swipe behavior,
ensuring that the swipe state remains consistent after layout
validation.
 
Additionally, a defensive improvement is introduced by clearing the
_swipeItems dictionary before repopulating it in the UpdateSwipeItems()
method. This prevents duplicate key insertion and ensures that the
method behaves safely even if invoked multiple times under unexpected
conditions.

### Issues Fixed
Fixes dotnet#34917

### Validated the behaviour in the following platforms

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

### Output
| Before | After |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/55a131cb-6ccc-4776-80d7-90655651565d">
| <video
src="https://github.com/user-attachments/assets/5efc010e-04ec-4e4d-8729-d43f41d2d6bf">
|
@PureWeen PureWeen mentioned this pull request Jun 2, 2026
PureWeen added a commit that referenced this pull request Jun 2, 2026
## What's Coming

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


## Button
- [Android, iOS] Button: Fix VisualState properties not restored when
leaving custom state by @BagavathiPerumal in
#33346
  <details>
  <summary>🔧 Fixes</summary>

- [Button VisualStates do not
work](#19690)
  </details>

## CollectionView
- Fix CollectionView grid spacing updates for first row and column by
@KarthikRajaKalaimani in #34527
  <details>
  <summary>🔧 Fixes</summary>

- [[MAUI] I2_Vertical grid for horizontal Item Spacing and Vertical Item
Spacing - horizontally updating the spacing only applies to the second
column](#34257)
  </details>

- CarouselView: Fix cascading PositionChanged/CurrentItemChanged events
on collection update by @praveenkumarkarunanithi in
#31275
  <details>
  <summary>🔧 Fixes</summary>

- [[Windows] CurrentItemChangedEventArgs and PositionChangedEventArgs
Not Working Properly in
CarouselView](#29529)
  </details>

- [Windows] Fixed ItemSpacing doesn't work in Carousel View by
@SubhikshaSf4851 in #30014
  <details>
  <summary>🔧 Fixes</summary>

- [ItemSpacing on CarouselView is not applied on
Windows.](#29772)
  </details>

- Fix CollectionView not scrolling to top on iOS status bar tap by
@jfversluis in #34687
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] UICollectionView ScrollToTop does not
work](#19866)
  </details>

- [iOS] Fixed CollectionView Scroll Jitter for TextType HTML Labels by
@SubhikshaSf4851 in #34383
  <details>
  <summary>🔧 Fixes</summary>

- [CollectionView scrolling is jittery when ItemTemplate contains Label
with TextType="Html" in .NET
10](#33065)
  </details>

- Fix CollectionView Header is not visible when ItemsSource is not set
and an EmptyView is set in iOS, Mac platform by @KarthikRajaKalaimani in
#34989
  <details>
  <summary>🔧 Fixes</summary>

- [CollectionView Header is not visible when ItemsSource is not set and
EmptyView is set in iOS, Mac
platform](#34897)
  </details>

- [Android] Fix CollectionView EmptyView not displayed correctly by
@KarthikRajaKalaimani in #34956
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] CollectionView - EmptyView not displayed
correctly](#34861)
  </details>

- [iOS] Fix CollectionView ScrollOffset not resetting when ItemsSource
changes by @SyedAbdulAzeemSF4852 in
#34488
  <details>
  <summary>🔧 Fixes</summary>

- [[IOS] CollectionView ScrollOffset does not reset when the ItemSource
is changed in iOS.](#26366)
- [Re-enable Issue7993 test on iOS/Catalyst - CollectionView scroll
position not reset when updating
ItemsSource](#33500)
  </details>

- [Revert] [iOS] Fixed CollectionView Scroll Jitter for TextType HTML
Labels by @SubhikshaSf4851 in #35341

## Core Lifecycle
- [Android] Fix NRE in ContainerView when Android Context is null during
lifecycle transition by @rmarinho in
#34901
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] NullReferenceException in NavigationRootManager.Connect
when mapping Window
content](#34900)
  </details>

## DateTimePicker
- [Android] Fix for TimePicker Dialog doesn't update the layout when
rotating the device with dialog open by @HarishwaranVijayakumar in
#31910
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] TimePicker Dialog doesn't update the layout when rotating
the device with dialog
open](#31658)
  </details>

- [Android, iOS] Fixed TimePicker FlowDirection Not Applied Across
Platforms by @Dhivya-SF4094 in #30369
  <details>
  <summary>🔧 Fixes</summary>

- [TimePicker FlowDirection Not Working on All
Platforms](#30192)
  </details>

- [Windows] Fixed TimePicker CharacterSpacing issue by @SubhikshaSf4851
in #30533
  <details>
  <summary>🔧 Fixes</summary>

- [[Windows] TimePicker CharacterSpacing Property Not Working on
Windows](#30199)
  </details>

- [MacCatalyst] Fix DatePicker Opened/Closed events not being raised by
@SubhikshaSf4851 in #34970
  <details>
  <summary>🔧 Fixes</summary>

- [[MacCatalyst] DatePicker Opened and Closed events are not raised on
Mac platform](#34848)
  </details>

## Dialogalert
- [Android] Fix AlertDialog, ActionSheet, and Prompt render with
Material 2 styles when Material 3 is enabled by @HarishwaranVijayakumar
in #35121
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] AlertDialog, ActionSheet, and Prompt render with Material 2
styles when Material 3 is
enabled](#35119)
  </details>

## Docs
- docs: Add UITesting-Guide, ReleasePlanning, and ReleaseProcess to
docs/README.md index by @PureWeen in
#35195

- docs: Fix hardcoded path and add library overview in Essentials.AI
README by @PureWeen in #35194

- docs: Update branch reference from net10.0 to net11.0 in
DEVELOPMENT.md by @PureWeen in #35193

## Drawing
- Fix Path Rendering Issue Inside StackLayout When Margin Is Set by
@Shalini-Ashokan in #28071
  <details>
  <summary>🔧 Fixes</summary>

- [Path does not render if it has
Margin](#13801)
  </details>

- Fixed FlowDirection property not working on Drawable control and
GraphicsView by @Dhivya-SF4094 in
#34557
  <details>
  <summary>🔧 Fixes</summary>

- [[Android, Windows, iOS, macOS] FlowDirection property not working on
BoxView Control](#34402)
  </details>

- [iOS & Mac] Fix image tile misalignment in GraphicsView ImagePaint by
@SubhikshaSf4851 in #34935
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] Image resized with ResizeMode.Fit is not rendered correctly in
GraphicsView](#34755)
  </details>

- Fix Shadow does not honour Styles by @KarthikRajaKalaimani in
#35081
  <details>
  <summary>🔧 Fixes</summary>

- [Shadow does not honour
Styles](#19560)
  </details>

## Entry
- [iOS/macCatalyst] Fix Entry and Editor BackgroundColor reset when set
to null by @Shalini-Ashokan in #34741
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS, Maccatalyst] Entry & Editor BackgroundColor not reset to
Null](#34611)
  </details>

- [Windows] Fix password Entry crash when setting text on empty field by
@praveenkumarkarunanithi in #33891
  <details>
  <summary>🔧 Fixes</summary>

- [[WinUI] Password Obfuscation causes unhandled
crash](#33334)
  </details>

## Essentials
- [Essentials] Use mean sea level altitude on Android API 34+ by
@KitKeen in #35097
  <details>
  <summary>🔧 Fixes</summary>

- [Add support for MslAltitudeMeters in Essentials Geolocation on
Android](#27554)
  </details>

## Flyout
- Fixed Flyout Not Displayed on Android When FlyoutWidth Is Set Only for
Desktop via OnIdiom by @NanthiniMahalingam in
#29028
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] FlyoutWidth with OnIdiom shows no
flyout](#13243)
  </details>

- Revert "[Windows] Fix Flyout/Locked mode header collapse regression
causing UI test failures on candidate branch" by @kubaflo in
#35339

- Revert "Revert "[Windows] Fix Flyout/Locked mode header collapse
regression causing UI test failures on candidate branch"" by @kubaflo in
#35342

## Flyoutpage
- Fix [Android] Title of FlyOutPage is not updating anymore after
showing a NonFlyOutPage by @KarthikRajaKalaimani in
#34839
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] Title of FlyOutPage is not updating anymore after showing a
NonFlyOutPage](#33615)
  </details>

## Label
- [iOS] Fix span Tap gesture on wrapped Label lines in iOS 26+ by
@SubhikshaSf4851 in #34640
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS]Span TapGestureRecognizer does not work on the second line of
the span, if the span is wrapped to the next
line](#34504)
  </details>

## Layout
- Fixed Stacklayout is not rendered when clip is applied and StackLayout
placed child to the Border control in iOS/ Mac platform by
@KarthikRajaKalaimani in #33330
  <details>
  <summary>🔧 Fixes</summary>

- [[Mac/iOS] StackLayout fails to render content while applying Clip,
and the layout is placed inside a Border with Background in .NET
MAUI](#33241)
  </details>

## Map
- Fix Changing Location on a Pin does nothing by @NirmalKumarYuvaraj in
#30201
  <details>
  <summary>🔧 Fixes</summary>

- [[Maps] [Regression from Xamarin.Forms.Maps] Changing Location on a
Pin does nothing](#12916)
  </details>

## Mediapicker
- [iOS] Fix HEIC images picked via PickPhotosAsync not displayed by
@HarishwaranVijayakumar in #34954
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] [Regression] HEIC images picked via PickPhotosAsync not
displayed](#34953)
  </details>

- [Android] Fix MediaPicker.PickPhotosAsync UnauthorizedAccessException
on API 28 and below by @HarishwaranVijayakumar in
#34981
  <details>
  <summary>🔧 Fixes</summary>

- [MediaPicker.PickPhotos fails to modify image, tries to load original
source, fails to load source on Android
9.0](#34889)
  </details>

## Pages
- [iOS] Fix ContentPage with ToolbarItem Clicked event leaks when
presented as modal page by @devanathan-vaithiyanathan in
#35009
  <details>
  <summary>🔧 Fixes</summary>

- [ContentPage with ToolbarItem Clicked event leaks when presented as
modal page](#34892)
  </details>

## Platform
- [Android] Fix OnBackButtonPressed not invoked for Shell by
@Dhivya-SF4094 in #35150
  <details>
  <summary>🔧 Fixes</summary>

- [On Screen Back Button Does Not Fire OnBackButtonPressed in
Android](#9095)
  </details>

## RadioButton
- Fix RadioButtonGroup not working with ContentView by @Dhivya-SF4094 in
#34781
  <details>
  <summary>🔧 Fixes</summary>

- [RadioButtonGroup not working with
ContentView](#34759)
  </details>

- [Windows] Fix for RadioButton BorderColor and BorderWidth not updated
at runtime by @SyedAbdulAzeemSF4852 in
#28335
  <details>
  <summary>🔧 Fixes</summary>

- [RadioButton Border color not working for focused visual
state](#15806)
  </details>

- [iOS] Fix RadioButton BackgroundColor bleeding outside CornerRadius by
@SyedAbdulAzeemSF4852 in #34844
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] RadioButton BackgroundColor bleeds outside
CornerRadius](#34842)
  </details>

## SafeArea
- [iOS] Fix stale bottom safe area after changing SafeAreaEdges with
keyboard open by @praveenkumarkarunanithi in
#35083
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] ContentPage bottom has white space after changing SafeAreaEdges
while keyboard is open](#34846)
  </details>

## ScrollView
- [Windows] Fix Preserve ScrollView offsets when Orientation changes to
Neither by @SubhikshaSf4851 in #34827
  <details>
  <summary>🔧 Fixes</summary>

- [[Windows] ScrollView offsets do not preserve when Orientation changes
to Neither](#34671)
  </details>

## Searchbar
- [iOS] Fix SearchBar unexpected left margin in iPad windowed mode on 26
Version by @SubhikshaSf4851 in #34704
  <details>
  <summary>🔧 Fixes</summary>

- [in iPad windowed mode SearchBar adds left margin equivaltent to
SafeAreaInsets when placed inside
grid](#34551)
  </details>

## Shell
- [Windows] Fix for Shell.FlyoutBehavior="Flyout" forces the title
height space above the tab bar even if the page title is empty by
@BagavathiPerumal in #30382
  <details>
  <summary>🔧 Fixes</summary>

- [(Windows) Shell.FlyoutBehavior="Flyout" forces the title height space
above the tab bar even if the page title is
empty](#30254)
  </details>

- Fix Shell flyout items scrolling behind FlyoutHeader on iOS by @Qythyx
in #34936
  <details>
  <summary>🔧 Fixes</summary>

- [Shell flyout items scroll behind FlyoutHeader on
iOS](#34925)
  </details>

- [iOS, Mac] Fix Shell.CurrentState.Location stale in OnNavigated after
GoToAsync by @Vignesh-SF3580 in
#34880
  <details>
  <summary>🔧 Fixes</summary>

- [Shell.OnNavigated not called for route
navigation](#34662)
  </details>

- [iOS26]Fix
BackButtonBehavior_IsEnabled_False_BackButtonDoesNotNavigate UITest
fails by @devanathan-vaithiyanathan in
#34890
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS 26] BackButtonBehavior_IsEnabled_False_BackButtonDoesNotNavigate
test fails with
TimeoutException](#34771)
  </details>

- [iOS] Fix Shell page memory leak when using TitleView with x:Name by
@Shalini-Ashokan in #35082
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] Title view memory
leak](#34975)
  </details>

- [Material 3] Fix Material 2 color flash in AppBar when switching tabs
for the first time by @Dhivya-SF4094 in
#35117
  <details>
  <summary>🔧 Fixes</summary>

- [Material 3: AppBar briefly displays Material 2 colors when switching
tabs for the first time](#35116)
  </details>

- [Android] Fix Shell/TabbedPage "More" BottomSheet uses hard-coded M2
colors when Material3 is enabled by @HarishwaranVijayakumar in
#35129
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] Shell/TabbedPage "More" BottomSheet uses hard-coded M2
colors when Material3 is
enabled](#35127)
  </details>

- [Android] Shell: Fix top-tab unselected text visibility in Material 3
light theme by @SyedAbdulAzeemSF4852 in
#35128
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] Shell top-tab unselected text appears too faint in Material
3 light theme](#35125)
  </details>

- Fix Shell.Items.Clear() memory leak by disconnecting child handlers on
removal (#34898) by @Shalini-Ashokan in
#35031
  <details>
  <summary>🔧 Fixes</summary>

- [Shell.Items.Clear() does not disconnect handlers
correctly](#34898)
  </details>

- [iOS&Mac] Fix Shell SearchHandler Query update on Initial load by
@SubhikshaSf4851 in #35008
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS&Mac] Shell SearchHandler Query not shown in search bar on
initial load](#35005)
  </details>

## SwipeView
- [iOS,MacCatalyst] Fix for SwipeView.Open() throwing an
ArgumentException on the second programmatic call by @BagavathiPerumal
in #34982
  <details>
  <summary>🔧 Fixes</summary>

- [[net 11.0][iOS,MacCatalyst] SwipeView.Open() throws ArgumentException
on second programmatic
call](#34917)
  </details>

- [Android/iOS] Fix SwipeItem visibility change causing double command
execution in Execute mode by @praveenkumarkarunanithi in
#35087
  <details>
  <summary>🔧 Fixes</summary>

- [Changing visibility on an SwipeItem causes multiple items to be
executed](#7580)
  </details>

## Switch
- [iOS] Fix Switch ThumbColor reset on iOS 26+ theme changes. by
@Shalini-Ashokan in #33953
  <details>
  <summary>🔧 Fixes</summary>

- [Switch ThumbColor not Initialized Using VisualStateManager on iOS
Device](#33783)
- [I9-On macOS 26.2, the "Animate scroll" button is white by default on
iOS and Maccatalyst
platforms.](#33767)
  </details>

## TabbedPage
- [Windows] TabbedPage: Refresh layout when NavigationView size changes
by @BagavathiPerumal in #26217
  <details>
  <summary>🔧 Fixes</summary>

- [TabbedPage - ScrollView not allowing scrolling when it
should](#26103)
- [TabbedPage App on resize hides page bottom
content](#11402)
- [Grid overflows child ContentPage of parent TabbedPage on initial load
and when resizing on
Windows](#20028)
  </details>

- [Android] Material 3 Fixed BottomNavigationView overflowing in Tabbed
page by @NirmalKumarYuvaraj in #35064
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] Material3 - TabbedPage bottom tabs overflowing the
contents](#35063)
  </details>

- [Windows] Fix for Multiple Tabs Being Selected in WinUI TabbedPage by
@SyedAbdulAzeemSF4852 in #33312
  <details>
  <summary>🔧 Fixes</summary>

- [WinUI TabbedPage can have multiple tabs
selected](#31799)
  </details>

## Theming
- [iOS] Fix StaticResource Hot Reload crash on iOS by @StephaneDelcroix
in #35020
  <details>
  <summary>🔧 Fixes</summary>

- [The maui app quit and no errors in error list after editing
ResourceDictionary XAML file on iOS Simulator with MAUI SR6
10.0.60](#35018)
  </details>

## Toolbar
- [Windows] Fix for CS1061 build error caused by missing
HasMenuBarContent property in MauiToolbar by @BagavathiPerumal in
#35040

## Tooling
- Fix VisualStateGroups duplicate name crash with implicit styles
(#34716) by @StephaneDelcroix in
#34719
  <details>
  <summary>🔧 Fixes</summary>

- [SourceGen: VisualStateManager.VisualStateGroups causes 'Names must be
unique' at startup](#34716)
  </details>

## WebView
- Refactor the HybridWebView and properly support complex parameters by
@mattleibow in #32491

- [Android] Fix WebView scrolling inside ScrollView by @Shalini-Ashokan
in #33133
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] WebView's content does not scroll when placed inside a
ScrollView](#32971)
  </details>


<details>
<summary>🔧 Infrastructure (1)</summary>

- [Windows] Fix Narrator announcing ContentView children twice when
Description is set by @praveenkumarkarunanithi in
#33979
  <details>
  <summary>🔧 Fixes</summary>

- [[Windows] SemanticProperties.Description announced twice when set on
focusable container cell (Label
inside)](#33373)
  </details>

</details>

<details>
<summary>🧪 Testing (14)</summary>

- [Testing] SafeArea Feature Matrix Test Cases for ContentPage by
@TamilarasanSF4853 in #34877
- [Windows] Fix CollectionView ScrollTo related test cases failed in CI
by @HarishwaranVijayakumar in #34907
  <details>
  <summary>🔧 Fixes</summary>

- [[Testing][Windows]CollectionView ScrollTo related test cases failed
in CI](#34772)
  </details>
- [Testing] Fixed Build error on inflight/ candidate PR 35234 by
@HarishKumarSF4517 in #35241
- Fix CI for
ValidateKeyboardRuntime_SwitchContainerToSoftInput_WhileKeyboardOpen
test failure in May 4th Candidate by @devanathan-vaithiyanathan in
#35307
- [Windows] Fix Flyout/Locked mode header collapse regression causing UI
test failures on candidate branch by @BagavathiPerumal in
#35312
- [iOS/macCatalyst] [Candidate Fix] Editor shadow and theme regression
caused by BackgroundColor reset on initial handler connection by
@Shalini-Ashokan in #35343
- [Testing] Fixed UI test image failure in PR 35234 - [30/03/2026]
Candidate - 1 by @HarishKumarSF4517 in
#35325
- [iOS] Fix ShellFeatureMatrix test failures on candidate branch by
@Vignesh-SF3580 in #35346
- [Windows] Fix Issue29529VerifyPreviousPositionOnInsert test failure on
candidate branch by @praveenkumarkarunanithi in
#35398
- [Android] [Candidate Fix] Shell: Fix handler disconnect timing to
preserve WebView navigation and memory leak fix by @Shalini-Ashokan in
#35417
- [Testing]Revert 'Fix Preserve ScrollView offsets when Orientation
changes to Neither' by @TamilarasanSF4853 in
#35412
- [Windows] Fix VerifyAllIndicatorDotsShowShadowsWhenIndicatorSize test
failure on candidate branch by @praveenkumarkarunanithi in
#35458
- [Testing] Fixed test failure in PR 35234 - [05/08/2026] Candidate by
@TamilarasanSF4853 in #35362
- [Testing] Fixed test failure in PR 35234 - [05/04/2026] Candidate - 3
by @TamilarasanSF4853 in #35639

</details>

<details>
<summary>📦 Other (6)</summary>

- [UIKit] Avoid useless measure invalidation propagation cycles by
@albyrock87 in #33459
- BindableObject property access micro-optimizations by @albyrock87 in
#33584
- Extract filename from DisplayName and add extension if missing by
@mattleibow in #35050
- [core] Add keyed-DI screenshot extensibility for 3rd-party platform
backends by @Redth in #35096
  <details>
  <summary>🔧 Fixes</summary>

- [`ViewExtensions.CaptureAsync(IView)` and `IPlatformScreenshot` need
extensibility for third-party platform
backends](#34266)
  </details>
- Fix MainThread throwing on custom platform backends by @Redth in
#35070
  <details>
  <summary>🔧 Fixes</summary>

- [`MainThread.BeginInvokeOnMainThread` throws on custom platform
backends - Common UI-thread marshaling pattern crashes; `Dispatcher`
works but isn't the documented/recommended
path](#34101)
  </details>
- Tests: Add 11 missing UnitConverters unit tests by @PureWeen in
#35191

</details>

<details>
<summary>📝 Issue References</summary>

Fixes #7580, Fixes #9095, Fixes #11402, Fixes #12916, Fixes #13243,
Fixes #13801, Fixes #15806, Fixes #19560, Fixes #19690, Fixes #19866,
Fixes #20028, Fixes #26103, Fixes #26366, Fixes #27554, Fixes #29529,
Fixes #29772, Fixes #30192, Fixes #30199, Fixes #30254, Fixes #31658,
Fixes #31799, Fixes #32971, Fixes #33065, Fixes #33241, Fixes #33334,
Fixes #33373, Fixes #33500, Fixes #33615, Fixes #33767, Fixes #33783,
Fixes #34101, Fixes #34257, Fixes #34266, Fixes #34402, Fixes #34504,
Fixes #34551, Fixes #34611, Fixes #34662, Fixes #34671, Fixes #34716,
Fixes #34755, Fixes #34759, Fixes #34771, Fixes #34772, Fixes #34842,
Fixes #34846, Fixes #34848, Fixes #34861, Fixes #34889, Fixes #34892,
Fixes #34897, Fixes #34898, Fixes #34900, Fixes #34917, Fixes #34925,
Fixes #34953, Fixes #34975, Fixes #35005, Fixes #35018, Fixes #35063,
Fixes #35116, Fixes #35119, Fixes #35125, Fixes #35127

</details>

**Full Changelog**:
main...inflight/candidate
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-controls-swipeview SwipeView community ✨ Community Contribution partner/macios Issues for the Mac / iOS SDK partner/syncfusion Issues / PR's with Syncfusion collaboration platform/ios s/agent-approved AI agent recommends approval - PR fix is correct and optimal s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-gate-passed AI verified tests catch the bug (fail without fix, pass with fix) s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[net 11.0][iOS,MacCatalyst] SwipeView.Open() throws ArgumentException on second programmatic call

7 participants