Simple Way to bind Selected Item Changed to View Model

As we know together, in Xamarin we can bind command and command parameter to a button. That command will be fired when button is clicked and we can pass parameter through command parameter. But it’s kinda more complicated when it comes to picker or list view. We have selected index changed and item selected in picker and list view respectively to handle the event when user pick a certain item, but we need function in back-end to capture the event before we process it to view model. We also can use behavior to bind the event directly to view model, but it’s bit too complicated for me, especially to do simple task like this. And recently I found a simple workaround to address this problem.

Property Binding

What I do is binding the Selected Item property to certain variable in view model. The binding mode can be one way to source, or two way if you want to initialize the selected item. Continuing from my previous post, I will use picker instead of list view in this example. I will also use the custom picker that I used in previous post. But the trick will also works for list view.

I’ve created two pickers in xaml file and the value that bind to the second picker will be depended to what user choose in first picker.   Here’s how the code look like.

<?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:control="clr-namespace:App1.CustomControls" x:Class="App1.Pages.PizzaPage">
  <ContentPage.Content>
   <StackLayout VerticalOptions="Center" Padding="30,0,30,0">
    <Label Text="Choose your Pizza!!!"  TextColor="#118E8C" FontSize="Large"/>
    <control:CustomPicker Title="Select Pizza Country" ItemsSource="{Binding CountryList}" FontSize="48" SelectedItem="{Binding SelectedCountry, Mode=TwoWay}"/>
    <control:CustomPicker Title="Select Pizza Type" ItemsSource="{Binding PizzaList}" FontSize="42"/>
   </StackLayout>
  </ContentPage.Content>
 </ContentPage>

Selected Item Handling

As you can see, in the first picker, Selected Item property is bind to property named Selected Country. In the view model, when this variable is set, I will call function to update the list that is bind to the second picker. So, whenever user change his choice in first picker, the value of second picker will also change simultaneously. The following code is how the view model look like.

public class PizzaViewModel : INotifyPropertyChanged
{
  private ObservableCollection<string> countryList;
  private ObservableCollection<string> pizzaList;
  private string selectedCountry;

  public ObservableCollection<string> CountryList
  {
    get => countryList;
    set
    {
      SetObservableProperty(ref countryList, value);
    }
  }
  public ObservableCollection<string> PizzaList
  {
   get => pizzaList;
   set => SetObservableProperty(ref pizzaList, value);
  }

  public string SelectedCountry
  {
    get => selectedCountry;
    set
    {
      if (value != selectedCountry && value != null)
      LoadPizzaType(value);
      SetObservableProperty(ref selectedCountry, value);
    }
}

public event PropertyChangedEventHandler PropertyChanged;

public PizzaViewModel()
{
  LoadPizzaCountry();
}

private async void LoadPizzaCountry()
{
  CountryList = await PizzaServices.GetPizzaCountry();
}

private async void LoadPizzaType(string country)
{
  PizzaList = await PizzaServices.GetPizzaType(country);
}

protected void SetObservableProperty<T>(ref T field, T value,
[CallerMemberName] string propertyName = "")
{
  if (EqualityComparer<T>.Default.Equals(field, value)) return;
  field = value;
  OnPropertyChanged(propertyName);
}

protected virtual void OnPropertyChanged(string propertyName)
 => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

Take a look at variable Selected Country, it’s where the trick lies. With this simple trick, you can bind something similar like command and command parameter in one packet to picker and list view.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s