0
votes

When binding to a picker, you can use ItemDisplayBinding to bind the displayed value, but I do not see a way to map each item to a selection value. Because of this, I'm having to write some very convoluted code to keep my pickers in sync with data source changes.

Original Model

// NOTE: this implements INPC, just abbreviated for clarity
public class DataModel
{
  public ICollection<DataItem> Items;
  pubilc DataItem SelectedItem;
}

Original Picker:

<Picker Title="Select Item..." 
        ItemsSource="{Binding Items}"
        ItemDisplayBinding="{Binding Name}"
        SelectedItem="{Binding Path=SelectedItem}"></Picker>

New Model

// NOTE: this implements INPC, just abbreviated for clarity
public class DataModel
{
  public ICollection<DataItems> Items;
  public ICollection<string> ItemNames;
  public DataItem SelectedItem;
  public string SelectedItemName;
  public DataModel()
  {
     this.PropertyChanged += (s, e) => 
     {
       // I feel like I shouldn't have to do this...
       if(StringComparer.Ordinal.Equals(e.PropertyName, nameof(Items)))
       {
          if(!String.IsNullOrWhitespace(this.SelectedItemName))
          {
             this.SelectedItem = this.Items.FirstOrDefault(x => StringComparer.Ordinal.Equals(x.Name, this.SelectedItemName));
             if (this.SelectedItem == null) { this.SelectedItemName = null; }
          }
       }
  }
}

New Picker:

<Picker Title="Select Item..."
        ItemsSource="{Binding ItemNames}"
        SelectedItem="{Binding Path=SelectedItemName}"></Picker>

I would like to be able to do something like this:

<Picker Title="Select Item..."
        ItemsSource="{Binding Items}"
        ItemDisplayBinding="{Binding Name}"
        ItemValueBinding="{Binding Name}"
        SelectedItem="{Binding Path=SelectedItemName}"></Picker>

I do not need a reference to the item, I need a property off of it. In this way, when the Items collection changes, it automatically reselects the correct item if it's still present. I find that I'm adding a second collection everywhere with just the properties I want to choose and doing all this mapping. Every other platform I've worked on, this is pretty straight forward, so I feel like I have to be missing something with Xamarin.Forms.

1
I think you don't need to do this.The SelectedItem property data binds to the SelectedItem(in your original model) property of the connected view model, which is of type DataItem. Therefore, when the user selects an item in the Picker, the SelectedItem property will be set to the selected DataItem object automatically.Leo Zhu - MSFT

1 Answers

0
votes

I think you don't need to do this.The SelectedItem property data binds to the SelectedItem(in your original model) property of the connected view model, which is of type DataItem. Therefore, when the user selects an item in the Picker, the SelectedItem property will be set to the selected DataItem object automatically.

You could test it in its SelectedIndexChanged event like:

<Picker Title="Select Item..." 
    ItemsSource="{Binding Items}"
    ItemDisplayBinding="{Binding Name}"
    SelectedItem="{Binding Path=SelectedItem}"
    SelectedIndexChanged="Picker_SelectedIndexChanged">
 </Picker>

 private void Picker_SelectedIndexChanged(object sender, EventArgs e)
    {
        Picker picker = sender as Picker;
        DataItem dt = picker.SelectedItem as DataItem ;
        Console.WriteLine(dt.Name); // you will see when you select a item,the SelectedItem will be changed automatically
    }

And i suggest you use ObservableCollection<Item> Items, so it will automatically update your Items when it changes.