Skip to content

[Windows] Fix for RadioButton BorderColor and BorderWidth not updated at runtime#28335

Merged
kubaflo merged 14 commits into
dotnet:inflight/currentfrom
SyedAbdulAzeemSF4852:fix-15806
Apr 17, 2026
Merged

[Windows] Fix for RadioButton BorderColor and BorderWidth not updated at runtime#28335
kubaflo merged 14 commits into
dotnet:inflight/currentfrom
SyedAbdulAzeemSF4852:fix-15806

Conversation

@SyedAbdulAzeemSF4852

@SyedAbdulAzeemSF4852 SyedAbdulAzeemSF4852 commented Mar 12, 2025

Copy link
Copy Markdown
Contributor

Issue Details

  • The radio button's BorderColor and BorderWidth are not updated at runtime.

Root Cause

  • Handling of runtime changes for BorderColor and BorderWidth has not been implemented.

Description of Change

  • Implemented the OnPropertyChanged method to check if the changed property is either BorderColor or BorderWidth. If so, then updated the StrokeColor or StrokeThickness of the radio button in the handler accordingly.

Reference :

protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)

Validated the behaviour in the following platforms

  • Windows
  • Android
  • iOS
  • Mac

Issues Fixed

Fixes #15806

Output

Before Fix After Fix
RadioButtonBorderColorNotChanged.mp4
RadioButtonBorderColorChanged.mp4

@dotnet-policy-service dotnet-policy-service Bot added community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration labels Mar 12, 2025
@jsuarezruiz jsuarezruiz added the area-controls-radiobutton RadioButton, RadioButtonGroup label Mar 12, 2025
@jsuarezruiz

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@SyedAbdulAzeemSF4852 SyedAbdulAzeemSF4852 changed the title [Windows] Fix for RadioButton BorderColor not working for Focused Visual State [Windows] Fix for RadioButton BorderColor and BorderWidth not updated at runtime. Mar 13, 2025
@SyedAbdulAzeemSF4852 SyedAbdulAzeemSF4852 changed the title [Windows] Fix for RadioButton BorderColor and BorderWidth not updated at runtime. [Windows] Fix for RadioButton BorderColor and BorderWidth not updated at runtime Mar 13, 2025
@jsuarezruiz

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@SyedAbdulAzeemSF4852 SyedAbdulAzeemSF4852 marked this pull request as ready for review March 14, 2025 10:38
@SyedAbdulAzeemSF4852 SyedAbdulAzeemSF4852 requested a review from a team as a code owner March 14, 2025 10:38

@jsuarezruiz jsuarezruiz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you commit the pending snapshots?
image

@SyedAbdulAzeemSF4852

Copy link
Copy Markdown
Contributor Author

@jsuarezruiz , I have committed the pending snapshots.

@jsuarezruiz

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@jsuarezruiz jsuarezruiz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The default RadioButton border width is -1:

public static readonly BindableProperty BorderWidthProperty = BindableProperty.Create(nameof(IBorderElement.BorderWidth), typeof(double), typeof(IBorderElement), -1d);

In the sample, set the BorderColor (Normal state) to Red color but, not assign a value to BorderWidth.

The snapshot on any platform not render the border, as expected:

But on Windows:

Could you review it?

@SyedAbdulAzeemSF4852

Copy link
Copy Markdown
Contributor Author

@jsuarezruiz , Previously, on Windows, if the BorderWidth was not explicitly specified, it would default to a Thickness object with a value of 3. As a result, the border would appear visible on Windows even though no border width was set, which could lead to inconsistencies in the UI across different platforms. Later it was fixed in this PR.

In addition to setting the BorderColor, I have also included the BorderWidth in the test case to ensure consistent behavior across all platforms. This ensures that the border styling (both color and width) is applied uniformly, making the appearance of the RadioButton consistent regardless of the platform.

@jsuarezruiz

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@jsuarezruiz

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@jsuarezruiz

Copy link
Copy Markdown
Contributor

/rebase

@jsuarezruiz

Copy link
Copy Markdown
Contributor

/azp run MAUI-UITests-public

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@dotnet dotnet deleted a comment from MauiBot Apr 16, 2026
@dotnet dotnet deleted a comment from MauiBot Apr 16, 2026
@MauiBot

MauiBot commented Apr 16, 2026

Copy link
Copy Markdown
Collaborator

🚦 Gate — Test Before and After Fix

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

🚦 Gate Sessionf9a0967 · updated baseline snapshot · 2026-04-16 19:07 UTC

Gate Result: ✅ PASSED

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

Test Without Fix (expect FAIL) With Fix (expect PASS)
🖥️ Issue15806 Issue15806 ✅ FAIL — 550s ✅ PASS — 450s
🔴 Without fix — 🖥️ Issue15806: FAIL ✅ · 550s
  Determining projects to restore...
  Restored D:\a\1\s\src\Controls\Maps\src\Controls.Maps.csproj (in 51.39 sec).
  Restored D:\a\1\s\src\Controls\src\Core\Controls.Core.csproj (in 51.61 sec).
  Restored D:\a\1\s\src\Controls\Foldable\src\Controls.Foldable.csproj (in 396 ms).
  Restored D:\a\1\s\src\BlazorWebView\src\Maui\Microsoft.AspNetCore.Components.WebView.Maui.csproj (in 3.71 sec).
  Restored D:\a\1\s\src\Graphics\src\Graphics.Win2D\Graphics.Win2D.csproj (in 24 ms).
  Restored D:\a\1\s\src\Essentials\src\Essentials.csproj (in 16 ms).
  Restored D:\a\1\s\src\Core\src\Core.csproj (in 82 ms).
  Restored D:\a\1\s\src\Core\maps\src\Maps.csproj (in 24 ms).
  Restored D:\a\1\s\src\Graphics\src\Graphics\Graphics.csproj (in 3.57 sec).
  Restored D:\a\1\s\src\Controls\src\Xaml\Controls.Xaml.csproj (in 19 ms).
  Restored D:\a\1\s\src\Controls\tests\TestCases.HostApp\Controls.TestCases.HostApp.csproj (in 892 ms).
  3 of 14 projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  Graphics -> D:\a\1\s\artifacts\bin\Graphics\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  Essentials -> D:\a\1\s\artifacts\bin\Essentials\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Essentials.dll
  Graphics.Win2D -> D:\a\1\s\artifacts\bin\Graphics.Win2D\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Graphics.Win2D.WinUI.Desktop.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  Core -> D:\a\1\s\artifacts\bin\Core\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.dll
  Controls.BindingSourceGen -> D:\a\1\s\artifacts\bin\Controls.BindingSourceGen\Debug\netstandard2.0\Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  Controls.Core -> D:\a\1\s\artifacts\bin\Controls.Core\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  Controls.Xaml -> D:\a\1\s\artifacts\bin\Controls.Xaml\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.Xaml.dll
  Controls.Foldable -> D:\a\1\s\artifacts\bin\Controls.Foldable\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.Foldable.dll
  Microsoft.AspNetCore.Components.WebView.Maui -> D:\a\1\s\artifacts\bin\Microsoft.AspNetCore.Components.WebView.Maui\Debug\net10.0-windows10.0.19041.0\Microsoft.AspNetCore.Components.WebView.Maui.dll
  Maps -> D:\a\1\s\artifacts\bin\Maps\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Maps.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  Controls.Maps -> D:\a\1\s\artifacts\bin\Controls.Maps\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.Maps.dll
  Controls.TestCases.HostApp -> D:\a\1\s\artifacts\bin\Controls.TestCases.HostApp\Debug\net10.0-windows10.0.19041.0\win-x64\Controls.TestCases.HostApp.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:05:38.82
  Determining projects to restore...
  Restored D:\a\1\s\src\TestUtils\src\VisualTestUtils\VisualTestUtils.csproj (in 724 ms).
  Restored D:\a\1\s\src\TestUtils\src\UITest.NUnit\UITest.NUnit.csproj (in 2.27 sec).
  Restored D:\a\1\s\src\TestUtils\src\UITest.Core\UITest.Core.csproj (in 3 ms).
  Restored D:\a\1\s\src\TestUtils\src\VisualTestUtils.MagickNet\VisualTestUtils.MagickNet.csproj (in 5.54 sec).
  Restored D:\a\1\s\src\TestUtils\src\UITest.Appium\UITest.Appium.csproj (in 2.41 sec).
  Restored D:\a\1\s\src\Controls\tests\TestCases.WinUI.Tests\Controls.TestCases.WinUI.Tests.csproj (in 4.96 sec).
  Restored D:\a\1\s\src\Controls\tests\CustomAttributes\Controls.CustomAttributes.csproj (in 4 ms).
  Restored D:\a\1\s\src\TestUtils\src\UITest.Analyzers\UITest.Analyzers.csproj (in 9.19 sec).
  7 of 15 projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  Graphics -> D:\a\1\s\artifacts\bin\Graphics\Debug\net10.0\Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  Essentials -> D:\a\1\s\artifacts\bin\Essentials\Debug\net10.0\Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  Controls.CustomAttributes -> D:\a\1\s\artifacts\bin\Controls.CustomAttributes\Debug\net10.0\Controls.CustomAttributes.dll
  Core -> D:\a\1\s\artifacts\bin\Core\Debug\net10.0\Microsoft.Maui.dll
  Controls.Core.Design -> D:\a\1\s\artifacts\bin\Controls.Core.Design\Debug\net472\Microsoft.Maui.Controls.DesignTools.dll
  Controls.BindingSourceGen -> D:\a\1\s\artifacts\bin\Controls.BindingSourceGen\Debug\netstandard2.0\Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  Controls.Core -> D:\a\1\s\artifacts\bin\Controls.Core\Debug\net10.0\Microsoft.Maui.Controls.dll
  UITest.Core -> D:\a\1\s\artifacts\bin\UITest.Core\Debug\net10.0\UITest.Core.dll
  UITest.Appium -> D:\a\1\s\artifacts\bin\UITest.Appium\Debug\net10.0\UITest.Appium.dll
  UITest.NUnit -> D:\a\1\s\artifacts\bin\UITest.NUnit\Debug\net10.0\UITest.NUnit.dll
  VisualTestUtils -> D:\a\1\s\artifacts\bin\VisualTestUtils\Debug\netstandard2.0\VisualTestUtils.dll
  VisualTestUtils.MagickNet -> D:\a\1\s\artifacts\bin\VisualTestUtils.MagickNet\Debug\netstandard2.0\VisualTestUtils.MagickNet.dll
  UITest.Analyzers -> D:\a\1\s\artifacts\bin\UITest.Analyzers\Debug\netstandard2.0\UITest.Analyzers.dll
  Controls.TestCases.WinUI.Tests -> D:\a\1\s\artifacts\bin\Controls.TestCases.WinUI.Tests\Debug\net10.0\Controls.TestCases.WinUI.Tests.dll
Test run for D:\a\1\s\artifacts\bin\Controls.TestCases.WinUI.Tests\Debug\net10.0\Controls.TestCases.WinUI.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (x64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
D:\a\1\s\artifacts\bin\Controls.TestCases.WinUI.Tests\Debug\net10.0\Controls.TestCases.WinUI.Tests.dll
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in D:\a\1\s\artifacts\bin\Controls.TestCases.WinUI.Tests\Debug\net10.0\Controls.TestCases.WinUI.Tests.dll
   NUnit3TestExecutor discovered 1 of 1 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 4/16/2026 6:59:55 PM FixtureSetup for Issue15806(Windows)
>>>>> 4/16/2026 7:00:04 PM ValidateRadioButtonBorderColor Start
>>>>> 4/16/2026 7:00:07 PM ValidateRadioButtonBorderColor Stop
>>>>> 4/16/2026 7:00:07 PM Log types: 
  Failed ValidateRadioButtonBorderColor [3 s]
  Error Message:
   VisualTestUtils.VisualTestFailedException : 
Snapshot different than baseline: ValidateRadioButtonBorderColor.png (0.86% difference)
If the correct baseline has changed (this isn't a a bug), then update the baseline image.
See test attachment or download the build artifacts to get the new snapshot file.

More info: https://aka.ms/visual-test-workflow

  Stack Trace:
     at VisualTestUtils.VisualRegressionTester.Fail(String message) in /_/src/TestUtils/src/VisualTestUtils/VisualRegressionTester.cs:line 162
   at VisualTestUtils.VisualRegressionTester.VerifyMatchesSnapshot(String name, ImageSnapshot actualImage, String environmentName, ITestContext testContext) in /_/src/TestUtils/src/VisualTestUtils/VisualRegressionTester.cs:line 123
   at Microsoft.Maui.TestCases.Tests.UITest.<VerifyScreenshot>g__Verify|13_0(String name, <>c__DisplayClass13_0&) in /_/src/Controls/tests/TestCases.Shared.Tests/UITest.cs:line 477
   at Microsoft.Maui.TestCases.Tests.UITest.VerifyScreenshot(String name, Nullable`1 retryDelay, Nullable`1 retryTimeout, Int32 cropLeft, Int32 cropRight, Int32 cropTop, Int32 cropBottom, Double tolerance, Boolean includeTitleBar) in /_/src/Controls/tests/TestCases.Shared.Tests/UITest.cs:line 309
   at Microsoft.Maui.TestCases.Tests.Issues.Issue15806.ValidateRadioButtonBorderColor() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue15806.cs:line 20
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

NUnit Adapter 4.5.0.0: Test execution complete
[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.14]   Discovering: Controls.TestCases.WinUI.Tests
[xUnit.net 00:00:00.43]   Discovered:  Controls.TestCases.WinUI.Tests

Total tests: 1
     Failed: 1
Test Run Failed.
 Total time: 30.9080 Seconds

🟢 With fix — 🖥️ Issue15806: PASS ✅ · 450s
  Determining projects to restore...
  All projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  Graphics -> D:\a\1\s\artifacts\bin\Graphics\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  Graphics.Win2D -> D:\a\1\s\artifacts\bin\Graphics.Win2D\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Graphics.Win2D.WinUI.Desktop.dll
  Essentials -> D:\a\1\s\artifacts\bin\Essentials\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  Core -> D:\a\1\s\artifacts\bin\Core\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.dll
  Controls.BindingSourceGen -> D:\a\1\s\artifacts\bin\Controls.BindingSourceGen\Debug\netstandard2.0\Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  Maps -> D:\a\1\s\artifacts\bin\Maps\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Maps.dll
  Controls.Core -> D:\a\1\s\artifacts\bin\Controls.Core\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  Controls.Xaml -> D:\a\1\s\artifacts\bin\Controls.Xaml\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.Xaml.dll
  Controls.Foldable -> D:\a\1\s\artifacts\bin\Controls.Foldable\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.Foldable.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  Microsoft.AspNetCore.Components.WebView.Maui -> D:\a\1\s\artifacts\bin\Microsoft.AspNetCore.Components.WebView.Maui\Debug\net10.0-windows10.0.19041.0\Microsoft.AspNetCore.Components.WebView.Maui.dll
  Controls.Maps -> D:\a\1\s\artifacts\bin\Controls.Maps\Debug\net10.0-windows10.0.19041.0\Microsoft.Maui.Controls.Maps.dll
  Controls.TestCases.HostApp -> D:\a\1\s\artifacts\bin\Controls.TestCases.HostApp\Debug\net10.0-windows10.0.19041.0\win-x64\Controls.TestCases.HostApp.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:05:28.60
  Determining projects to restore...
  All projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  Graphics -> D:\a\1\s\artifacts\bin\Graphics\Debug\net10.0\Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  Essentials -> D:\a\1\s\artifacts\bin\Essentials\Debug\net10.0\Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  Core -> D:\a\1\s\artifacts\bin\Core\Debug\net10.0\Microsoft.Maui.dll
  Controls.CustomAttributes -> D:\a\1\s\artifacts\bin\Controls.CustomAttributes\Debug\net10.0\Controls.CustomAttributes.dll
  Controls.Core.Design -> D:\a\1\s\artifacts\bin\Controls.Core.Design\Debug\net472\Microsoft.Maui.Controls.DesignTools.dll
  Controls.BindingSourceGen -> D:\a\1\s\artifacts\bin\Controls.BindingSourceGen\Debug\netstandard2.0\Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13859157
  Controls.Core -> D:\a\1\s\artifacts\bin\Controls.Core\Debug\net10.0\Microsoft.Maui.Controls.dll
  UITest.Core -> D:\a\1\s\artifacts\bin\UITest.Core\Debug\net10.0\UITest.Core.dll
  UITest.Appium -> D:\a\1\s\artifacts\bin\UITest.Appium\Debug\net10.0\UITest.Appium.dll
  VisualTestUtils -> D:\a\1\s\artifacts\bin\VisualTestUtils\Debug\netstandard2.0\VisualTestUtils.dll
  UITest.NUnit -> D:\a\1\s\artifacts\bin\UITest.NUnit\Debug\net10.0\UITest.NUnit.dll
  VisualTestUtils.MagickNet -> D:\a\1\s\artifacts\bin\VisualTestUtils.MagickNet\Debug\netstandard2.0\VisualTestUtils.MagickNet.dll
  UITest.Analyzers -> D:\a\1\s\artifacts\bin\UITest.Analyzers\Debug\netstandard2.0\UITest.Analyzers.dll
  Controls.TestCases.WinUI.Tests -> D:\a\1\s\artifacts\bin\Controls.TestCases.WinUI.Tests\Debug\net10.0\Controls.TestCases.WinUI.Tests.dll
Test run for D:\a\1\s\artifacts\bin\Controls.TestCases.WinUI.Tests\Debug\net10.0\Controls.TestCases.WinUI.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (x64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
D:\a\1\s\artifacts\bin\Controls.TestCases.WinUI.Tests\Debug\net10.0\Controls.TestCases.WinUI.Tests.dll
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in D:\a\1\s\artifacts\bin\Controls.TestCases.WinUI.Tests\Debug\net10.0\Controls.TestCases.WinUI.Tests.dll
   NUnit3TestExecutor discovered 1 of 1 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 4/16/2026 7:07:29 PM FixtureSetup for Issue15806(Windows)
>>>>> 4/16/2026 7:07:37 PM ValidateRadioButtonBorderColor Start
>>>>> 4/16/2026 7:07:39 PM ValidateRadioButtonBorderColor Stop
  Passed ValidateRadioButtonBorderColor [1 s]
NUnit Adapter 4.5.0.0: Test execution complete
[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.12]   Discovering: Controls.TestCases.WinUI.Tests
[xUnit.net 00:00:00.38]   Discovered:  Controls.TestCases.WinUI.Tests

Test Run Successful.
Total tests: 1
     Passed: 1
 Total time: 24.0138 Seconds

📁 Fix files reverted (8 files)
  • 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-windows/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/RadioButton/RadioButton.cs

@MauiBot

MauiBot commented Apr 16, 2026

Copy link
Copy Markdown
Collaborator

🤖 AI Summary

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

📊 Review Sessionf9a0967 · updated baseline snapshot · 2026-04-16 20:12 UTC
🔍 Pre-Flight — Context & Validation

Issue: #15806 - RadioButton Border color not working for focused visual state
PR: #28335 - [Windows] Fix for RadioButton BorderColor and BorderWidth not updated at runtime
Platforms Affected: Windows (primary), Android (secondary — handler has real MapStrokeColor implementation)
Files Changed: 1 implementation (RadioButton.cs), 2 test files (Issue15806.cs x2), 1 snapshot, 7 PublicAPI.Unshipped.txt files

Key Findings

  • RadioButton never bridged BorderColorProperty/BorderWidthProperty BindableProperty changes to the handler mapper, causing runtime updates (e.g., from VSM setters) to be silently ignored
  • Fix mirrors the exact pattern in Button.cs (referenced by the author) — override OnPropertyChanged and call Handler?.UpdateValue for the relevant mapper keys
  • IBorderElement.OnBorderColorPropertyChanged in RadioButton is an intentional no-op; OnPropertyChanged is the correct bridge
  • Test uses CommonStates with Normal and Focused visual states — structurally correct for Windows focus transitions
  • Test correctly skipped on Android/iOS/Catalyst due to known focus event limitation (issue RadioButton Focused and Unfocused Events Not Firing on iOS and Android #28163)
  • All 7 PublicAPI.Unshipped.txt files updated with ~override entry — correct pattern matching other controls like Button

Code Review Summary

Verdict: NEEDS_CHANGES
Confidence: medium
Errors: 0 | Warnings: 3 | Suggestions: 2

Key code review findings:

  • ⚠️ CI showing Build Analysis and overall maui-pr failures — needs investigation before merge (RadioButton.cs:375)
  • ⚠️ Unresolved Copilot review thread about test correctness (thread appears stale but needs explicit resolution)
  • ⚠️ Fix is cross-platform but test only covers Windows; no test coverage on Android for non-focus BorderColor changes
  • 💡 using System.Runtime.CompilerServices import is justified for [CallerMemberName]
  • 💡 ~ prefix in PublicAPI files is consistent with established pattern

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #28335 Override OnPropertyChanged in RadioButton.cs to call Handler?.UpdateValue(StrokeColor/StrokeThickness) when BorderColorProperty/BorderWidthProperty change ✅ PASSED (Gate) RadioButton.cs, 2 test files, 7 PublicAPI files Mirrors Button.cs pattern exactly

🔬 Code Review — Deep Analysis

Code Review — PR #28335

Independent Assessment

What this changes: RadioButton.cs gains an OnPropertyChanged override that calls Handler?.UpdateValue(nameof(IRadioButton.StrokeColor)) when BorderColorProperty changes, and similarly for BorderWidthStrokeThickness. Two UI test files are added for issue #15806, plus a Windows snapshot.

Inferred motivation: RadioButton implements IBorderElement and exposes BorderColor/BorderWidth as BindablePropertys, but the handler mapper keyed on IRadioButton.StrokeColor/StrokeThickness was never told to re-run when those bindable properties changed. So VSM setters that change BorderColor (e.g., when focus is gained/lost) were silently swallowed — the handler never received the update and the native border remained stale.


Reconciliation with PR Narrative

Author claims: Fix for BorderColor and BorderWidth not updating at runtime; validated on Windows only; models the approach after Button.cs (referenced explicitly in the PR).

Agreement: The author's diagnosis and approach are correct. The root cause matches the code, and the reference to Button.cs is accurate — the pattern is identical.

Minor disagreement: The PR title says [Windows], but the change is in cross-platform RadioButton.cs and runs on all platforms. On Android, MapStrokeColor has a real implementation; on iOS it's a no-op. The fix is broader than Windows, but the only observable visual effect is on Windows and Android (where handlers actually apply the stroke).


Findings

⚠️ Warning — CI showing overall maui-pr failures

Build Analysis and the overall maui-pr check are reporting fail. Individual pipeline steps appear to mostly pass, but the overall failure is unclear. The author should confirm whether these are pre-existing infra flakes or caused by this PR before merge.

⚠️ Warning — Unresolved review comment about test correctness

An earlier Copilot review thread claims the test conflates "Checked" and "Focused" state. The current diff shows "CommonStates" with "Normal" and "Focused" states — which is the correct VSM group. That prior comment appears stale/outdated, but the thread is still open and not marked resolved. The author should explicitly address it.

⚠️ Warning — Test exercises only Windows; the fix is cross-platform

The test is wrapped in:

#if TEST_FAILS_ON_ANDROID && TEST_FAILS_ON_IOS && TEST_FAILS_ON_CATALYST

The comment cites issue #28163 (Focused/Unfocused events not firing on non-Windows). Legitimate for "Focused" state, but the OnPropertyChanged bridge fires on all platforms whenever a VSM setter updates BorderColor — not just focus events. Android's MapStrokeColor does have a real implementation. There's no test coverage on Android for the non-focus case.

💡 Suggestion — using System.Runtime.CompilerServices; import is justified

The PR adds this import for [CallerMemberName]. This is correct — Button.cs uses the same attribute. No action needed.

💡 Suggestion — ~ prefix in PublicAPI.Unshipped.txt

All 7 platform files correctly add:

~override Microsoft.Maui.Controls.RadioButton.OnPropertyChanged(string propertyName = null) -> void

The ~ prefix is consistent with other ~override entries. The nullability difference (string vs string?) is expected because RadioButton.cs has #nullable disable. Low-priority but confirming via dotnet format analyzers is a good practice.


Devil's Advocate

"Is calling Handler?.UpdateValue in OnPropertyChanged duplicating work?"
BorderElement.BorderColorProperty has a propertyChanged callback: OnBorderColorPropertyChanged(Color, Color). RadioButton's implementation of that interface method is intentionally empty. No double-update risk; the two mechanisms are independent.

"Could calling UpdateValue during property change cause reentrancy?"
Handler?.UpdateValue dispatches to the mapper, which reads IRadioButton.StrokeColor (backed by the BindableProperty). No write occurs; no cycle.

"Is this fix sound on Android?"
Android's MapStrokeColor calls GetPlatformRadioButton(handler)?.UpdateStrokeColor(radioButton) — a real implementation. The fix has observable effect on Android for VSM or programmatic BorderColor change. iOS maps are no-ops, consistent with the platform's ControlTemplate-based rendering path.

"Could Button have regressed when its identical OnPropertyChanged was added?"
Button.cs has had this pattern for a long time without issue. RadioButton's handler mapper already registered StrokeColor/StrokeThickness keys — this PR just ensures those mapper entries are triggered at the right time.


Verdict: NEEDS_CHANGES

Confidence: medium

Errors: 0 | Warnings: 3 | Suggestions: 2

The core logic change (OnPropertyChanged override) is correct, minimal, and follows the established Button.cs pattern precisely. PublicAPI files are properly updated. The blockers are: (1) CI showing Build Analysis and overall maui-pr failures that must be explained/resolved, and (2) an unresolved Copilot review thread that should be explicitly addressed.


🔧 Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix (claude-opus-4.6) Add ["BorderColor"] = MapStrokeColor and ["BorderWidth"] = MapStrokeThickness alias entries to RadioButtonHandler.Mapper in RadioButtonHandler.cs ✅ Pass 1 file (+4 lines) No new public API; handler-level fix; cleanest
2 try-fix (claude-sonnet-4.6) Fill in IBorderElement.OnBorderColorPropertyChanged + replace BorderWidthProperty with new BindableProperty with propertyChanged lambda ✅ Pass 1 file No OnPropertyChanged override; uses existing interface hook; potential breaking change for BorderWidthProperty reference
3 try-fix (gpt-5.3-codex) Controls-layer remap in RadioButton.RemapForControls() adding ReplaceMapping for BorderColor/BorderWidth → stroke handlers ✅ Pass 1 file Controls-layer redirect; more indirection than needed
4 try-fix (gpt-5.4) Windows-specific INotifyPropertyChanged subscription in RadioButtonHandler.Windows.cs ConnectHandler/DisconnectHandler ✅ Pass 1 file (+27 lines) Windows-only; doesn't address cross-platform; more complex
PR PR #28335 Override OnPropertyChanged in RadioButton.cs calling Handler?.UpdateValue(StrokeColor/StrokeThickness) ✅ PASSED (Gate) RadioButton.cs + 7 PublicAPI files + 2 test files Mirrors Button.cs pattern; adds public API surface for all 7 platforms

Cross-Pollination

Model Round New Ideas? Details
claude-opus-4.6 2 No Design space exhausted — all architectural layers covered

Exhausted: Yes

Selected Fix: Candidate #1 (mapper aliases in RadioButtonHandler.cs) — Better than PR's fix

Reasoning:

  • Candidate [Draft] Readme WIP #1 is simpler (4 lines vs 13+ lines) and touches only 1 file
  • No new public API surface — PR's fix requires updating all 7 PublicAPI.Unshipped.txt files with ~override RadioButton.OnPropertyChanged
  • The handler mapper is the architecturally correct place: the root cause is a mapper registration gap ("BorderColor" not mapped), and the fix corrects it at the source
  • All 4 independent candidates passed, confirming multiple valid approaches exist
  • Candidate Update README.md #2 creates a new BindableProperty instance (potential breaking change for code referencing RadioButton.BorderWidthProperty == BorderElement.BorderWidthProperty)
  • Candidates Third #3 and Aloha System.Maui! #4 add more indirection or are Windows-only

📋 Report — Final Recommendation

⚠️ Final Recommendation: REQUEST CHANGES

Phase Status

Phase Status Notes
Pre-Flight ✅ COMPLETE Issue #15806, Windows RadioButton BorderColor/BorderWidth runtime update
Code Review NEEDS_CHANGES (medium) 0 errors, 3 warnings, 2 suggestions
Gate ✅ PASSED windows
Try-Fix ✅ COMPLETE 4 attempts, 4 passing
Report ✅ COMPLETE

Code Review Impact on Try-Fix

The code review noted that the PR's fix adds public API surface (~override OnPropertyChanged) across all 7 platforms unnecessarily — this directly motivated exploring handler-level alternatives. Attempt 1 (claude-opus-4.6) found a cleaner fix (4-line mapper alias) that avoids all PublicAPI changes. The warning about cross-platform coverage with Windows-only test influenced Attempt 4 (Windows-specific handler subscription), which also passed but was more complex. The failure-mode probes (null BorderColor handling, reentrancy) were confirmed safe by the code review's Devil's Advocate analysis and no changes were needed there.

Summary

PR #28335 fixes a real and verified bug: RadioButton.BorderColor and BorderWidth changes at runtime (e.g., from VisualStateManager setters) are silently swallowed because the handler mapper never receives the update notification. The fix is functionally correct and Gate-verified on Windows. However, a simpler alternative exists that avoids adding new public API surface across all 7 platforms.

The recommendation is REQUEST CHANGES to suggest the simpler mapper-alias approach — not because the PR's fix is wrong, but because a 4-line change in 1 file accomplishes the same goal with less churn.

Root Cause

RadioButton.BorderColorProperty and BorderWidthProperty are BindableProperty aliases to BorderElement's properties. When their values change (e.g., via VSM), Element.OnPropertyChanged fires with "BorderColor" / "BorderWidth" and dispatches to the handler mapper. However, the mapper only registered keys for "StrokeColor" / "StrokeThickness" (the IRadioButton interface names). The "BorderColor" and "BorderWidth" string keys had no mapper entries, so the notifications were dropped with no effect on the native view.

Fix Quality

PR's fix (override OnPropertyChanged in RadioButton.cs): Correct and follows the Button.cs precedent. However, it adds ~override RadioButton.OnPropertyChanged to all 7 PublicAPI.Unshipped.txt files, broadens the public API surface unnecessarily, and adds 13 lines of cross-platform code for what is fundamentally a mapper registration gap.

Better alternative (mapper alias entries in RadioButtonHandler.cs): Add 4 lines to RadioButtonHandler.Mapper:

["BorderColor"] = MapStrokeColor,
["BorderWidth"] = MapStrokeThickness,

This fixes the registration gap at the source, requires no PublicAPI.Unshipped.txt changes, no new using directives, and is fully tested and verified. Verified: ✅ PASSED ValidateRadioButtonBorderColor on Windows.

Note: The test structure is valid — it uses CommonStates VSM group with Normal and Focused states, which is the correct structure. The prior Copilot review thread about test correctness appears stale (it referenced "CheckedStates" which is not in the current code). The author should close that thread. The #if TEST_FAILS_ON_ANDROID && TEST_FAILS_ON_IOS && TEST_FAILS_ON_CATALYST guard is appropriate given issue #28163.


@kubaflo kubaflo changed the base branch from main to inflight/current April 17, 2026 08:38
@kubaflo kubaflo merged commit 7e08d24 into dotnet:inflight/current Apr 17, 2026
1 of 2 checks passed
@github-actions github-actions Bot added this to the .NET 10 SR7 milestone Apr 17, 2026
devanathan-vaithiyanathan pushed a commit to Tamilarasan-Paranthaman/maui that referenced this pull request Apr 21, 2026
… at runtime (dotnet#28335)

### Issue Details
- The radio button's BorderColor and BorderWidth are not updated at
runtime.

### Root Cause
- Handling of runtime changes for BorderColor and BorderWidth has not
been implemented.

### Description of Change
- Implemented the OnPropertyChanged method to check if the changed
property is either BorderColor or BorderWidth. If so, then updated the
StrokeColor or StrokeThickness of the radio button in the handler
accordingly.

### Reference : 

https://github.com/dotnet/maui/blob/ac01bde86e5105c1ca9c121c68c2a068a9f3ef27/src/Controls/src/Core/Button/Button.cs#L472

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

### Issues Fixed
Fixes dotnet#15806 

### Output
| Before Fix | After Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/3476b4aa-6670-4d6a-b471-506b42b3e9c3">
| <video
src="https://github.com/user-attachments/assets/880b40ca-ddda-4174-b621-d74dbb5853c4">
|

---------

Co-authored-by: Jakub Florkowski <[email protected]>
PureWeen pushed a commit that referenced this pull request Apr 22, 2026
… at runtime (#28335)

### Issue Details
- The radio button's BorderColor and BorderWidth are not updated at
runtime.

### Root Cause
- Handling of runtime changes for BorderColor and BorderWidth has not
been implemented.

### Description of Change
- Implemented the OnPropertyChanged method to check if the changed
property is either BorderColor or BorderWidth. If so, then updated the
StrokeColor or StrokeThickness of the radio button in the handler
accordingly.

### Reference : 

https://github.com/dotnet/maui/blob/ac01bde86e5105c1ca9c121c68c2a068a9f3ef27/src/Controls/src/Core/Button/Button.cs#L472

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

### Issues Fixed
Fixes #15806 

### Output
| Before Fix | After Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/3476b4aa-6670-4d6a-b471-506b42b3e9c3">
| <video
src="https://github.com/user-attachments/assets/880b40ca-ddda-4174-b621-d74dbb5853c4">
|

---------

Co-authored-by: Jakub Florkowski <[email protected]>
PureWeen pushed a commit that referenced this pull request Apr 28, 2026
… at runtime (#28335)

### Issue Details
- The radio button's BorderColor and BorderWidth are not updated at
runtime.

### Root Cause
- Handling of runtime changes for BorderColor and BorderWidth has not
been implemented.

### Description of Change
- Implemented the OnPropertyChanged method to check if the changed
property is either BorderColor or BorderWidth. If so, then updated the
StrokeColor or StrokeThickness of the radio button in the handler
accordingly.

### Reference : 

https://github.com/dotnet/maui/blob/ac01bde86e5105c1ca9c121c68c2a068a9f3ef27/src/Controls/src/Core/Button/Button.cs#L472

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

### Issues Fixed
Fixes #15806 

### Output
| Before Fix | After Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/3476b4aa-6670-4d6a-b471-506b42b3e9c3">
| <video
src="https://github.com/user-attachments/assets/880b40ca-ddda-4174-b621-d74dbb5853c4">
|

---------

Co-authored-by: Jakub Florkowski <[email protected]>
PureWeen pushed a commit that referenced this pull request Apr 29, 2026
… at runtime (#28335)

### Issue Details
- The radio button's BorderColor and BorderWidth are not updated at
runtime.

### Root Cause
- Handling of runtime changes for BorderColor and BorderWidth has not
been implemented.

### Description of Change
- Implemented the OnPropertyChanged method to check if the changed
property is either BorderColor or BorderWidth. If so, then updated the
StrokeColor or StrokeThickness of the radio button in the handler
accordingly.

### Reference : 

https://github.com/dotnet/maui/blob/ac01bde86e5105c1ca9c121c68c2a068a9f3ef27/src/Controls/src/Core/Button/Button.cs#L472

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

### Issues Fixed
Fixes #15806 

### Output
| Before Fix | After Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/3476b4aa-6670-4d6a-b471-506b42b3e9c3">
| <video
src="https://github.com/user-attachments/assets/880b40ca-ddda-4174-b621-d74dbb5853c4">
|

---------

Co-authored-by: Jakub Florkowski <[email protected]>
github-actions Bot pushed a commit that referenced this pull request May 6, 2026
… at runtime (#28335)

### Issue Details
- The radio button's BorderColor and BorderWidth are not updated at
runtime.

### Root Cause
- Handling of runtime changes for BorderColor and BorderWidth has not
been implemented.

### Description of Change
- Implemented the OnPropertyChanged method to check if the changed
property is either BorderColor or BorderWidth. If so, then updated the
StrokeColor or StrokeThickness of the radio button in the handler
accordingly.

### Reference : 

https://github.com/dotnet/maui/blob/ac01bde86e5105c1ca9c121c68c2a068a9f3ef27/src/Controls/src/Core/Button/Button.cs#L472

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

### Issues Fixed
Fixes #15806 

### Output
| Before Fix | After Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/3476b4aa-6670-4d6a-b471-506b42b3e9c3">
| <video
src="https://github.com/user-attachments/assets/880b40ca-ddda-4174-b621-d74dbb5853c4">
|

---------

Co-authored-by: Jakub Florkowski <[email protected]>
@github-actions github-actions Bot locked and limited conversation to collaborators May 17, 2026
@kubaflo kubaflo added s/agent-gate-passed AI verified tests catch the bug (fail without fix, pass with fix) and removed s/agent-gate-failed AI could not verify tests catch the bug labels May 20, 2026
@PureWeen PureWeen modified the milestones: .NET 10 SR7, .NET 10 SR8 Jun 11, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-controls-radiobutton RadioButton, RadioButtonGroup community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration platform/windows s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-win AI found a better alternative fix than the PR 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.

RadioButton Border color not working for focused visual state

9 participants