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