Home > Enterprise >  Xamarin SelectedValue in a CollectionView of RadioButton returns null
Xamarin SelectedValue in a CollectionView of RadioButton returns null

Time:11-09

I'm new to Xamarin and I'm still in the process of getting the gist of it. I wanted to make a collection view of radio buttons, but whenever I submit the selection returns null instead of the supposed value.

Here is my code:

View

       <StackLayout>
            <CollectionView ItemsSource="{Binding choices}"
                            RadioButtonGroup.SelectedValue="{Binding choice}">
                <CollectionView.ItemTemplate>
                    <DataTemplate>
                        <RadioButton Content="{Binding .}" Value="{Binding .}"/>
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </CollectionView>
            <Button Text="Submit" Command="{Binding submit}"/>
        </StackLayout>

ViewModel

    public ObservableRangeCollection<string> choices { get; set; }
        public toTestVM()
        {
            choices = new ObservableRangeCollection<string>();
            List<string> tempList = new List<string>() { "Cat", "Dog", "Bird", "Chicken", "Cow","Fish"};
            choices.AddRange(tempList);
            submit = new AsyncCommand(promptAnswer);
        }
        public ICommand submit { get; }
        private string _choice;
        public string choice
        {
            get => _choice;
            set => SetProperty(ref _choice, value);
        }
        public async Task promptAnswer()
        {
            if (!String.IsNullOrEmpty(_choice))
            {
                await App.Current.MainPage.DisplayAlert("", _choice, "OK");
            }
        }
   }

The answer doesn't prompt whenever I click submit since _choice remains null despite having OnPropertyChange();

I'll be grateful for any help or advice. Thank you

The choices list views well in a radiobutton form. But even if I select one and click submit, the answer still returns null. Is there something wrong with the code>

CodePudding user response:

But even if I select one and click submit, the answer still returns null. Is there something wrong with the code>

That's because there is a conflict between event CheckedChanged of RadioButton and event SelectionChanged of collectionview.

You can create a DataTemplate for the CollectionView.

Based on your code, I created a demo. I could get the Choice if I select an item.

Please refer to the following code:

TestPage.xaml

<?xml version="1.0" encoding="utf-8" ?> 
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:app1109="clr-namespace:App1109"
             x:Class="App1109.TestPage2"
             x:Name="MyPageName"
             >
    <ContentPage.BindingContext>
        <app1109:TestViewModel></app1109:TestViewModel>
    </ContentPage.BindingContext>
    <ContentPage.Content>
        <StackLayout>
            <CollectionView ItemsSource="{Binding choices}" x:Name="collectionView"
                            SelectedItem="{Binding Choice}"
                            SelectionMode="Single"
                            >
                <CollectionView.ItemTemplate>
                    <DataTemplate>
                        <StackLayout Orientation="Horizontal" x:Name="Item" >
                            <RadioButton Content="{Binding Name}" IsChecked="{Binding IsSelected}" WidthRequest="160"  >
                                <RadioButton.Behaviors>
                                    <app1109:EventToCommandBehavior 
                                    EventName="CheckedChanged"     
                                    Command="{Binding BindingContext.MyRadioCommand, Source={x:Reference Name=MyPageName}}" CommandParameter="{Binding .}"
                                                               />
                                </RadioButton.Behaviors>
                            </RadioButton>
                        </StackLayout>
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </CollectionView>
            <Button Text="Submit" Command="{Binding submit}"/>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

TestViewModel.cs

public class TestViewModel: INotifyPropertyChanged 
    {
        public ObservableCollection<ItemModel> choices { get; set; }
        public TestViewModel()
        {
            List<ItemModel> tempList = new List<ItemModel>() { new ItemModel{ Name= "Cat" }, new ItemModel { Name = "Dog" } , new ItemModel { Name = "Bird" ,IsSelected = true} , new ItemModel { Name = "Chicken" }, new ItemModel { Name = "Cow" }, new ItemModel { Name = "Fish" } };

            choices = new ObservableCollection<ItemModel>(tempList);
        }

        public ICommand submit => new Command(promptAnswer);

        public ICommand MyRadioCommand => new Command<ItemModel>(changeStateMethod);

        public async void changeStateMethod(ItemModel item) {

            await App.Current.MainPage.DisplayAlert("", item.Name, "OK");
        }

         ItemModel _choice;
        public ItemModel Choice
        {
            get => _choice;
            set => SetProperty(ref _choice, value);
        }

        public async void promptAnswer()
        {
            if (Choice !=null)
            {
                await App.Current.MainPage.DisplayAlert("", Choice.Name, "OK");
            }
        }

        bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
        {
            if (Object.Equals(storage, value))
                return false;
            storage = value;
            OnPropertyChanged(propertyName);
            return true;
        }
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }

ItemModel.cs

   public class ItemModel: INotifyPropertyChanged 
    {
        public string Name { get; set; }

        private bool _isSelected;
        public bool IsSelected
        {
            set { SetProperty(ref _isSelected, value); }
            get { return _isSelected; }
        }

        bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
        {
            if (Object.Equals(storage, value))
                return false;
            storage = value;
            OnPropertyChanged(propertyName);
            return true;
        }
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }

Note:

For EventToCommandBehavior.cs, you can refer sample code here: https://github.com/xamarin/xamarin-forms-samples/tree/main/Behaviors/EventToCommandBehavior/EventToCommandBehavior/Behaviors

  • Related