-
Notifications
You must be signed in to change notification settings - Fork 2k
[Issue-Resolver] Fix #33264 - RadioButtonGroup not working with Collection View #33343
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
80b78d3
cc7196b
a88b938
0b1eed3
27e5cb6
0aa6b4a
291f775
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,6 +24,8 @@ public RadioButtonGroupController(Maui.ILayout layout) | |
| _layout = (Element)layout; | ||
| _layout.ChildAdded += ChildAdded; | ||
| _layout.ChildRemoved += ChildRemoved; | ||
| _layout.DescendantAdded += DescendantAdded; | ||
| _layout.DescendantRemoved += DescendantRemoved; | ||
|
Comment on lines
+25
to
+26
|
||
|
|
||
| if (!string.IsNullOrEmpty(_groupName)) | ||
| { | ||
|
|
@@ -97,6 +99,30 @@ void ChildRemoved(object sender, ElementEventArgs e) | |
| } | ||
| } | ||
|
|
||
| void DescendantAdded(object sender, ElementEventArgs e) | ||
| { | ||
| if (string.IsNullOrEmpty(_groupName) || _layout == null) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| if (e.Element is RadioButton radioButton) | ||
| { | ||
| AddRadioButton(radioButton); | ||
| } | ||
| } | ||
|
|
||
| void DescendantRemoved(object sender, ElementEventArgs e) | ||
| { | ||
| if (e.Element is RadioButton radioButton) | ||
| { | ||
| if (groupControllers.TryGetValue(radioButton, out _)) | ||
| { | ||
| groupControllers.Remove(radioButton); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| internal void HandleRadioButtonValueChanged(RadioButton radioButton) | ||
| { | ||
| if (radioButton?.GroupName != _groupName) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| <?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.Issue33264" | ||
| Title="Issue 33264"> | ||
|
|
||
| <StackLayout Padding="20" Spacing="10" RadioButtonGroup.GroupName="choices" RadioButtonGroup.SelectedValue="{Binding SelectedValue}"> | ||
| <Label Text="RadioButtonGroup not working with CollectionView" FontSize="18" FontAttributes="Bold"/> | ||
|
|
||
| <Label Text="Select an option below:" FontSize="14"/> | ||
|
|
||
| <CollectionView ItemsSource="{Binding Choices}" AutomationId="ChoicesCollectionView"> | ||
| <CollectionView.ItemTemplate> | ||
| <DataTemplate> | ||
| <RadioButton Content="{Binding}" Value="{Binding}" GroupName="choices" AutomationId="{Binding}"/> | ||
| </DataTemplate> | ||
| </CollectionView.ItemTemplate> | ||
| </CollectionView> | ||
|
|
||
| <Label Text="Selected value:" FontSize="14" FontAttributes="Bold"/> | ||
| <Label Text="{Binding SelectedValueDisplay}" FontSize="16" AutomationId="SelectedValueLabel"/> | ||
| </StackLayout> | ||
| </ContentPage> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| using System.Collections.ObjectModel; | ||
| using System.ComponentModel; | ||
| using System.Runtime.CompilerServices; | ||
|
|
||
| namespace Maui.Controls.Sample.Issues; | ||
|
|
||
| [Issue(IssueTracker.Github, 33264, "RadioButtonGroup not working with CollectionView", PlatformAffected.All)] | ||
| public partial class Issue33264 : ContentPage | ||
| { | ||
| public Issue33264() | ||
| { | ||
| InitializeComponent(); | ||
| BindingContext = new Issue33264ViewModel(); | ||
| } | ||
|
|
||
| protected override void OnAppearing() | ||
| { | ||
| base.OnAppearing(); | ||
| Dispatcher.DispatchDelayed(TimeSpan.FromMilliseconds(500), () => | ||
| { | ||
| CaptureState("OnAppearing"); | ||
| }); | ||
| } | ||
|
|
||
| private void CaptureState(string context) | ||
| { | ||
| var vm = BindingContext as Issue33264ViewModel; | ||
| Console.WriteLine($"=== STATE CAPTURE: {context} ==="); | ||
| Console.WriteLine($"SelectedValue: {vm?.SelectedValue ?? "null"}"); | ||
| Console.WriteLine("=== END STATE CAPTURE ==="); | ||
| } | ||
| } | ||
|
|
||
| public class Issue33264ViewModel : INotifyPropertyChanged | ||
| { | ||
| private string _selectedValue; | ||
|
|
||
| public ObservableCollection<string> Choices { get; } = new ObservableCollection<string> | ||
| { | ||
| "Choice 1", | ||
| "Choice 2", | ||
| "Choice 3" | ||
| }; | ||
|
|
||
| public string SelectedValue | ||
| { | ||
| get => _selectedValue; | ||
| set | ||
| { | ||
| if (_selectedValue != value) | ||
| { | ||
| Console.WriteLine($"=== BINDING UPDATE: SelectedValue changing from '{_selectedValue}' to '{value}' ==="); | ||
| _selectedValue = value; | ||
| OnPropertyChanged(); | ||
| OnPropertyChanged(nameof(SelectedValueDisplay)); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| public string SelectedValueDisplay => string.IsNullOrEmpty(SelectedValue) ? "None" : SelectedValue; | ||
|
|
||
| public event PropertyChangedEventHandler PropertyChanged; | ||
|
|
||
| protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) | ||
| { | ||
| PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| using NUnit.Framework; | ||
| using UITest.Appium; | ||
| using UITest.Core; | ||
|
|
||
| namespace Microsoft.Maui.TestCases.Tests.Issues; | ||
|
|
||
| public class Issue33264 : _IssuesUITest | ||
| { | ||
| public override string Issue => "RadioButtonGroup not working with CollectionView"; | ||
|
|
||
| public Issue33264(TestDevice device) : base(device) { } | ||
|
|
||
| [Test] | ||
| [Category(UITestCategories.RadioButton)] | ||
| public void RadioButtonGroupBindingWorksInsideCollectionView() | ||
| { | ||
| // Wait for all elements to load | ||
| App.WaitForElement("ChoicesCollectionView"); | ||
| App.WaitForElement("Choice 2"); | ||
| App.WaitForElement("SelectedValueLabel"); | ||
|
|
||
| // Initially, SelectedValue should show "None" | ||
| var initialValue = App.FindElement("SelectedValueLabel").GetText(); | ||
| Console.WriteLine($"Initial SelectedValue: '{initialValue}'"); | ||
| Assert.That(initialValue, Is.EqualTo("None"), "Initial value should be 'None'"); | ||
|
|
||
| // Tap "Choice 2" radio button | ||
| App.Tap("Choice 2"); | ||
|
|
||
| // Wait for binding update by polling the label text | ||
| App.WaitForTextToBePresentInElement("SelectedValueLabel", "Choice 2"); | ||
|
|
||
| // Verify SelectedValue is updated | ||
| var selectedValue = App.FindElement("SelectedValueLabel").GetText(); | ||
| Console.WriteLine($"After tapping 'Choice 2', SelectedValue: '{selectedValue}'"); | ||
| Assert.That(selectedValue, Is.EqualTo("Choice 2"), "SelectedValue should be updated via binding when RadioButton is checked"); | ||
|
|
||
| // Tap "Choice 3" radio button | ||
| App.Tap("Choice 3"); | ||
|
|
||
| // Wait for binding update by polling the label text | ||
| App.WaitForTextToBePresentInElement("SelectedValueLabel", "Choice 3"); | ||
|
|
||
| // Verify SelectedValue is updated again | ||
| selectedValue = App.FindElement("SelectedValueLabel").GetText(); | ||
| Console.WriteLine($"After tapping 'Choice 3', SelectedValue: '{selectedValue}'"); | ||
| Assert.That(selectedValue, Is.EqualTo("Choice 3"), "SelectedValue should be updated when different RadioButton is checked"); | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.