Xamarin Forms Bindable Picker v2

Introduction

I’ve updated the BindablePicker from a previous blog post, added new features and created a github reopro for the code.

Xamarin Forms is a new and cool API for quickly building native apps for IOS, Android, and Windows UWP in C#.

The Xamarin Forms API comes with a primitive Picker control that lacks typical bindable properties that developers expect a Picker (similar functionally that a desktop ComboBox has) to have.

Xamarin Forms makes it very easy for developers to extend the API, write your own custom controls, or write custom renderers for controls.

This BindablePIcker is the result of studying blog and forum posts and receiving feedback and bug report on the original version.

API Comparison

Xamarin Forms Picker API

  • SelectedIndex (bindable)
  • Items (not bindable)

Bindable Picker API

  • ItemsSource (bindable)
  • SelectedItem (bindable)
  • SelectedValue (bindable)
  • DisplayMemberPath
  • SelectedValuePath

New Features Added

  • Support for collections that implement INotityCollectionChanged like the ObservableCollection

Bug Fixed

The original BindablePicker did not correctly set the SelectedItem after the ItemsSource was refreshed at runtime.

Bindable Picker Source

This repro contains a project that demonstrates scenarios for using this control and it has the source for the BindablePicker.

https://github.com/Oceanware/XamarinFormsBindablePicker

Training Video – XAML Power Toys BindablePicker Scenarios

This short video explains three common use cases for the BindablePicker.

Close

Have a great day.

Just a grain of sand on the worlds beaches.

26 comments

  1. Pingback: Xamarin Forms Bindable Picker | Oceanware
  2. Miguel Jesus

    Hello Karl, very thankfull for the BindablePicker component. I used it on a project i’ve been working on but i’m struggling on some “visual aspect”. When i start my page that has the BindablePicker i load my list of objects and then i would like to set the selected item to the first one of that list.

    I have:
    List DocumentTypesList
    and a
    DocumentTypeId
    to get the selected ID from the picker. Getting the value works fine, but setting the initial ID is not working for me, the picker has “choose item” as the value at first.

    My xaml:

    Like

    • Miguel Jesus

      I have:
      List[DocumentType] DocumentTypesList
      and a
      DocumentTypeId

      My xaml:
      [controls:BindablePicker x:Name=”DocumentTypePicker”
      DisplayMemberPath=”NeutralName”
      SelectedValuePath=”Id”
      ItemsSource=”{Binding Path=DocumentTypesList}”
      SelectedValue=”{Binding Path=DocumentTypeId, Mode=TwoWay}” /]

      Like

    • Victor

      Hi Karl,

      Thanks for the sharing this with us :). I’ve successfully integrated and test run the BindaPicker in my project couple days ago. Everything works fine as expected. I just have a question as following:

      Is it possible to set the default SelectedItem (when opened for the first time) to be the first element in the ItemSource? In the consuming View, I currently bind the SelectedItem to a string property in my ViewModel, and setting its value to the default value (myItemSource[0]), after the BindablePicker finishes loading initially, doesn’t yield any update in the view.

      Like

      • Victor

        So I kinda found what my problem was. In the demo repo above, I forgot to set the SelectedItem to myItemSource[0]. After I tried doing that, it works. So yeah no issue on the binding part.

        In my real application I have to asynchronously load the list (itemsource) from a remote endpoint. And then, inside the viewmodel, my mistake was placing the value-setting part for the SelectedItem outside the async Task (where it does the itemsource loading). I fixed it by moving that to inside the Task, right after the list is loaded successfully, so I was able to debug and see that SelectedItem is updated properly.

        A rising issue I notice now is that setting the default value for SelectedItem as described above (using async Task) wont change the placeholder text (which only changes if selects value using picker I believe). I think it’s a minor problem and maybe I’ll find out another way to go around this.

        Thanks again!

        Like

    • Miguel Jesus

      Hello Karl,

      The xamarin team made some changes to the Picker class and the BindablePicker started to behave in strange manners.

      Did you saw those changes on the forms core library? They boosted the Picker control, but don’t know if it’s a substitute to your implementation.

      Regards, Miguel.

      Like

  3. Karl

    Victor,

    You’re not raising property changed events for either of your properties. This is a BIG problem.

    public string SelectedReason { get; set; }
    public List RejectionReasons { get; set; }

    Also, you must update the view model properties on the UI thread.

    Best,

    Karl

    Like

    • Victor

      Thanks Karl,

      Sorry for getting back late. I see what you mean. I’m still pretty new with this whole data binding thing so I guess there are still quite a lot for me to read up on. Your suggestion should solve the issue, as I actually have used INotifyPropertyChanged in another viewmodel to bind a timepicker with a property that also has some preparation behind the scene. Thanks again 🙂

      Like

  4. anders-schultz

    Thank you so much. This control just worked for me after having tried multiple other ones. You saved my sanity this evening.

    Like

  5. Steve

    How would you implement dependency between two bindable pickers? For example, if the fields in your example video were reversed and the user selected country first and then were given a refreshed bindable picker of states (within the selected country) to choose from.

    Like

    • Karl

      My control has little to do with the programming task.

      You have to set up your view model to respond to a selecteditem of one control, and populate the items in the second control based on the selected item.

      Best,

      Karl

      Like

      • Steve

        Karl, thank you for the response, you are correct. I guess for completeness, I will share the approach I used, it is probably fairly common for people to have dependency between 2 or more pickers. In the Xaml cs I have code similar to the following:
        void lstCountry_ItemSelected(object sender, SelectedItemChangedEventArgs e)
        {
        string selId = ((CountryLookup)e.SelectedItem).ID;

        ((MyViewModel)this.BindingContext).LoadStateList(selId);
        }
        And, LoadStateList loads an ObservableCollection of states for the specified country.
        I guess I hadn’t consumed enough caffeine prior to asking my question. Thank you again for the feedback. I’m loving the bindable picker. Very helpful.

        Like

    • Steve

      I made a small change which you may want to include?
      If the bound list is cleared at runtime and an item was previously selected in the list, I was getting a NULL exception error. I added a null check on newValue in the following method, and that did the trick:
      static void OnSelectedItemChanged(BindableObject bindable, Object oldValue, Object newValue) {
      var boundPicker = (BindablePicker)bindable;
      if(newValue != null)
      boundPicker.ItemSelected?.Invoke(boundPicker, new SelectedItemChangedEventArgs(newValue));
      boundPicker.InternalSelectedItemChanged();
      }

      Liked by 1 person

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s