Skip to content

Commit

Permalink
[Android] Fix RadioButton selection in Group (#22787)
Browse files Browse the repository at this point in the history
* Revert changes to fix the issue

* Added repro sample

* Added UITest

* More samples

* Added new UITest

* Fix the issue

* Removed unnecessary changes

* Fixed test description

* Adding snapshots

* More snapshots
  • Loading branch information
jsuarezruiz committed Jun 5, 2024
1 parent c8ce71e commit df93d3a
Show file tree
Hide file tree
Showing 11 changed files with 301 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/Controls/src/Core/RadioButton/RadioButton.cs
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ bool MatchesScope(RadioButtonScopeMessage message)

void HandleRadioButtonGroupSelectionChanged(RadioButton selected, RadioButtonGroupSelectionChanged args)
{
if (!IsChecked || selected == this || string.IsNullOrEmpty(GroupName) || GroupName != selected.GroupName || object.Equals(Value, args.Value) || !MatchesScope(args))
if (!IsChecked || selected == this || string.IsNullOrEmpty(GroupName) || GroupName != selected.GroupName || (Value is not null && object.Equals(Value, args.Value)) || !MatchesScope(args))
{
return;
}
Expand Down
37 changes: 18 additions & 19 deletions src/Controls/tests/Core.UnitTests/RadioButtonTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ namespace Microsoft.Maui.Controls.Core.UnitTests
using Grid = Microsoft.Maui.Controls.Compatibility.Grid;
using StackLayout = Microsoft.Maui.Controls.Compatibility.StackLayout;


public class RadioButtonTests : BaseTestFixture
{
[Fact]
public void RadioButtonAddedToGroupGetsGroupName()
{
var layout = new StackLayout();
var groupName = "foo";
var radioButton = new RadioButton() { Value = 1 };
var radioButton = new RadioButton();

layout.SetValue(RadioButtonGroup.GroupNameProperty, groupName);
layout.Children.Add(radioButton);
Expand All @@ -26,7 +25,7 @@ public void NestedRadioButtonAddedToGroupGetsGroupName()
{
var layout = new StackLayout();
var groupName = "foo";
var radioButton = new RadioButton() { Value = 1 };
var radioButton = new RadioButton();

layout.SetValue(RadioButtonGroup.GroupNameProperty, groupName);

Expand Down Expand Up @@ -57,7 +56,7 @@ public void LayoutGroupNameAppliesToExistingRadioButtons()
{
var layout = new StackLayout();
var groupName = "foo";
var radioButton = new RadioButton() { Value = 1 };
var radioButton = new RadioButton();

layout.Children.Add(radioButton);
layout.SetValue(RadioButtonGroup.GroupNameProperty, groupName);
Expand All @@ -72,8 +71,8 @@ public void UpdatedGroupNameAppliesToRadioButtonsWithOldGroupName()
var groupName = "foo";
var updatedGroupName = "bar";
var otherGroupName = "other";
var radioButton1 = new RadioButton() { Value = 1 };
var radioButton2 = new RadioButton() { GroupName = otherGroupName, Value = 2 };
var radioButton1 = new RadioButton();
var radioButton2 = new RadioButton() { GroupName = otherGroupName };

layout.Children.Add(radioButton1);
layout.Children.Add(radioButton2);
Expand All @@ -90,10 +89,10 @@ public void ThereCanBeOnlyOne()
{
var groupName = "foo";

var radioButton1 = new RadioButton() { GroupName = groupName, Value = 1 };
var radioButton2 = new RadioButton() { GroupName = groupName, Value = 2 };
var radioButton3 = new RadioButton() { GroupName = groupName, Value = 3 };
var radioButton4 = new RadioButton() { GroupName = groupName, Value = 4 };
var radioButton1 = new RadioButton() { GroupName = groupName };
var radioButton2 = new RadioButton() { GroupName = groupName };
var radioButton3 = new RadioButton() { GroupName = groupName };
var radioButton4 = new RadioButton() { GroupName = groupName };

var layout = new Grid();

Expand All @@ -120,9 +119,9 @@ public void ThereCanBeOnlyOne()
[Fact]
public void ImpliedGroup()
{
var radioButton1 = new RadioButton() { Value = 1 };
var radioButton2 = new RadioButton() { Value = 2 };
var radioButton3 = new RadioButton() { Value = 3 };
var radioButton1 = new RadioButton();
var radioButton2 = new RadioButton();
var radioButton3 = new RadioButton();

var layout = new Grid();

Expand All @@ -146,9 +145,9 @@ public void ImpliedGroup()
[Fact]
public void ImpliedGroupDoesNotIncludeExplicitGroups()
{
var radioButton1 = new RadioButton() { Value = 1 };
var radioButton2 = new RadioButton() { Value = 2 };
var radioButton3 = new RadioButton() { GroupName = "foo", Value = 3 };
var radioButton1 = new RadioButton();
var radioButton2 = new RadioButton();
var radioButton3 = new RadioButton() { GroupName = "foo" };

var layout = new Grid();

Expand All @@ -167,9 +166,9 @@ public void ImpliedGroupDoesNotIncludeExplicitGroups()
[Fact]
public void RemovingSelectedButtonFromGroupClearsSelection()
{
var radioButton1 = new RadioButton() { GroupName = "foo", Value = 1 };
var radioButton2 = new RadioButton() { GroupName = "foo", Value = 2 };
var radioButton3 = new RadioButton() { GroupName = "foo", Value = 3 };
var radioButton1 = new RadioButton() { GroupName = "foo" };
var radioButton2 = new RadioButton() { GroupName = "foo" };
var radioButton3 = new RadioButton() { GroupName = "foo" };

radioButton1.IsChecked = true;
radioButton2.IsChecked = true;
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#if IOS
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues
{
public class Issue22183: _IssuesUITest
{
public Issue22183(TestDevice device) : base(device)
{
}

public override string Issue => "RadioButton with value cannot display selected state correctly";

[Test]
public void RadioButtonWithValueChangeSelected()
{
App.WaitForElement("TestCollectionView");

App.Tap("True_0");
App.Tap("False_0");

VerifyScreenshot();

App.Tap("True_1");
App.Tap("False_1");
}
}
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#if ANDROID
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues
{
public class Issue22750 : _IssuesUITest
{
public Issue22750(TestDevice device) : base(device)
{
}

public override string Issue => "Using radiobuttons in a group, pressing one button works fine, but pressing the second does not reset the first hence";

[Test]
public void RadioButtonUpdateValueInsideBorder()
{
App.WaitForElement("WaitForStubControl");

App.Tap("Yes");

App.Tap("No");
VerifyScreenshot("RadioButtonUpdateValueInsideBorderNo");

App.Tap("Yes");
VerifyScreenshot("RadioButtonUpdateValueInsideBorderYes");
}
}
}
#endif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
60 changes: 60 additions & 0 deletions src/Controls/tests/TestCases/Issues/Issue22183.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Maui.Controls.Sample.Issues.Issue22183"
xmlns:local="clr-namespace:Maui.Controls.Sample.Issues">
<AbsoluteLayout
VerticalOptions="Fill">
<CollectionView
AutomationId="TestCollectionView"
ItemsSource="{Binding ItemSource}"
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0,0,1,1">
<CollectionView.ItemTemplate>
<DataTemplate>
<VerticalStackLayout
x:DataType="local:Issue22183Model"
Padding="20"
Margin="0,0">
<Border Padding="10">
<VerticalStackLayout
RadioButtonGroup.GroupName="{Binding GroupId}"
RadioButtonGroup.SelectedValue="{Binding ShowOptions}">
<RadioButton
AutomationId="{Binding False}"
Content="{Binding False}"
VerticalOptions="Center">
<RadioButton.Value>
<x:Boolean>False</x:Boolean>
</RadioButton.Value>
</RadioButton>
<RadioButton
AutomationId="{Binding True}"
Content="{Binding True}"
VerticalOptions="Center">
<RadioButton.Value>
<x:Boolean>True</x:Boolean>
</RadioButton.Value>
</RadioButton>
</VerticalStackLayout>
</Border>
<VerticalStackLayout
IsVisible="{Binding ShowOptions}"
BindableLayout.ItemsSource="{Binding Options}">
<BindableLayout.ItemTemplate>
<DataTemplate x:DataType="local:Options">
<HorizontalStackLayout>
<CheckBox />
<Label
VerticalOptions="Center"
Text="{Binding Name}" />
</HorizontalStackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</VerticalStackLayout>
</VerticalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</AbsoluteLayout>
</ContentPage>
71 changes: 71 additions & 0 deletions src/Controls/tests/TestCases/Issues/Issue22183.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System.Collections.ObjectModel;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Xaml;

namespace Maui.Controls.Sample.Issues
{
[XamlCompilation(XamlCompilationOptions.Compile)]
[Issue(IssueTracker.Github, 22183, "RadioButton with value cannot display selected state correctly", PlatformAffected.iOS)]
public partial class Issue22183 : ContentPage
{
public Issue22183()
{
InitializeComponent();

BindingContext = new Issue22183ViewModel();
}
}

public class Issue22183ViewModel
{
public ObservableCollection<Issue22183Model> ItemSource { get; } = new ObservableCollection<Issue22183Model>(
[new Issue22183Model()
{
GroupId = 0,
},
new Issue22183Model()
{
GroupId = 1,
}]);
}

public class Issue22183Model : BindableObject
{
public int GroupId { get; set; }

public string False => $"False_{GroupId}";

public string True => $"True_{GroupId}";

public static readonly BindableProperty ShowOptionsProperty =
BindableProperty.Create(nameof(ShowOptions), typeof(bool), typeof(Issue22183Model));

public bool ShowOptions
{
set => SetValue(ShowOptionsProperty, value);
get => (bool)GetValue(ShowOptionsProperty);
}

public ObservableCollection<Options> Options { get; }

public Issue22183Model()
{
ShowOptions = false;

Options = new ObservableCollection<Options>();

for (int i = 0; i < 10; i++)
{
Options.Add(new Options
{
Name = $"Options_{i}",
});
}
}
}

public class Options
{
public string Name { get; set; }
}
}
40 changes: 40 additions & 0 deletions src/Controls/tests/TestCases/Issues/Issue22750.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Maui.Controls.Sample.Issues.Issue22750"
xmlns:ns="clr-namespace:Maui.Controls.Sample.Issues">
<Border
Padding="15,10,0,0">
<Border.Shadow>
<Shadow
Brush="{AppThemeBinding Light=LightGray, Dark=Gray}"
Offset="5,5"
Opacity="0.5"/>
</Border.Shadow>
<VerticalStackLayout>
<Label
AutomationId="WaitForStubControl"
Text="Lorem ipsum dolor sit amet"
FontAttributes="Bold" />
<Label
Text="{Binding Text}"
FontSize="Small"
HorizontalOptions="Start"
VerticalOptions="Start"
Padding="0,0,15,0"/>
<HorizontalStackLayout>
<RadioButton
Content="Yes"
AutomationId="Yes"
GroupName="Issue22750Group"
CheckedChanged="OnRadioButtonCheckedChanged" />
<RadioButton
Content="No"
AutomationId="No"
GroupName="Issue22750Group"
CheckedChanged="OnRadioButtonCheckedChanged" />
</HorizontalStackLayout>
</VerticalStackLayout>
</Border>
</ContentPage>
Loading

0 comments on commit df93d3a

Please sign in to comment.