17

I am using a XAMARIN picker to select a country. The countries are hard coded in the picker. Is there a way I could identify each country name through a key value. I have done this in a similar way using SAPUI5.

<core:Item key="AF" text="Afghanistan  " />
<core:Item key="AL" text="Albania  " />
<core:Item key="DZ" text="Algeria  " />
<core:Item key="VI" text="Amer.Virgin Is. " />

Similarily, is there a way for me to add a key value for each country in XAMARIN form picker?

4 Answers 4

29

There is a way of using Key-Value-Pairs in a Picker using Data Binding.

First you have to define the Dictionary in the Form's View Model and define a Property which returns a List of the Dictionaries Key-Value-Pairs. Also a Binding to the currently selected Item is needed:

class MyViewModel
{
  ...
  private Dictionary<string, string> PickerItems = 
    new Dictionary<string, string>() { {"AF", "Afghanistan"}, {"AL", "Albania" } };

  public List<KeyValuePair<string, string>> PickerItemList
  {
      get => PickerItems.ToList();
  }

  private KeyValuePair<string, string> _selectedItem;
  public KeyValuePair<string, string> SelectedItem
  {
      get => _selectedItem;
      set => _selectedItem = value;
  }
  ...
}

Second you have to set the Pickers ItemsSource, ItemDisplayBinding and SelectedItem Bindings in the Pickers definition:

<Picker
    ItemDisplayBinding="{Binding Value}"
    ItemsSource="{Binding PickerItemList}"
    SelectedItem="{Binding SelectedItem}" />

Given this, you can get the key of the selected Item in the View Model via

SelectedItem.Key

Further Reading: https://developer.xamarin.com/guides/xamarin-forms/user-interface/picker/populating-itemssource/#Populating_a_Picker_with_Data_Using_Data_Binding

Sign up to request clarification or add additional context in comments.

3 Comments

Excellent code sample. Still trying to fully understand how it all works together, but simplest example I could find. I was able to access the key and values of SelectedItem in the code behind pretty easily for anyone else that might want to do that.
Add this property to the picker in the xaml, and then name any method. <Picker SelectedIndexChanged="OnPickerChangedEvent" /> Call that method in the xaml.cs public void OnPickerChangedEvent(object sender, EventArgs e) { var picker = (Picker)sender; var myIndex = picker.SelectedIndex; var myData = this.MyViewModel.SelectedItem.Key; }
Excellent, simple example with clean code addressing the question directly. Thanks for the come-up; this should be the accepted answer
7

I was just facing the same problem and I found a way to do it. I just needed to bind a picker with a list of SomeClass elements. Here is what I did:

namespace MyApp.ViewModels 
{
    public class CboViewModel 
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
}

And then in my XAML file:

<ContentPage ...
    xmlns:vm="clr-namespace:MyApp.ViewModels;assembly=Myapp" >
    <ContentPage.Content>
        ...
        <Picker x:Name="pckStatus" HorizontalOptions="FillAndExpand" >
            <Picker.ItemsSource>
                <x:Array Type="{x:Type vm:CboViewModel}" >
                    <vm:CboViewModel Id="0" Name="All" />
                    <vm:CboViewModel Id="1" Name="New" />
                    <vm:CboViewModel Id="2" Name="Standby" />
                    <vm:CboViewModel Id="4" Name="In Progress" />
                    <vm:CboViewModel Id="8" Name="Submitted" />
                    <vm:CboViewModel Id="16" Name="Closed" />
                </x:Array>
            </Picker.ItemsSource>
            <Picker.ItemDisplayBinding>
                <Binding Path="Name" />
            </Picker.ItemDisplayBinding>
            <Picker.SelectedIndex>0</Picker.SelectedIndex>
        </Picker>
        ...
    <ContentPage.Content>
</ContentPage>

Comments

5

No, Key property is available in xamarin picker. But, you can implement it using Dictionary class and SelectedIndex property of xamarin picker class.

Implement it by using following code snippet :

class PickerDemoPage : ContentPage
        {
            // Dictionary to get Color from color name.
            Dictionary<string, Color> nameToColor = new Dictionary<string, Color>
            {
                { "Aqua", Color.Aqua }, { "Black", Color.Black },
                { "Blue", Color.Blue }, { "Fuschia", Color.Fuschia },
                { "Gray", Color.Gray }, { "Green", Color.Green },
                { "Lime", Color.Lime }, { "Maroon", Color.Maroon },
                { "Navy", Color.Navy }, { "Olive", Color.Olive },
                { "Purple", Color.Purple }, { "Red", Color.Red },
                { "Silver", Color.Silver }, { "Teal", Color.Teal },
                { "White", Color.White }, { "Yellow", Color.Yellow }
            };

            public PickerDemoPage()
            {
                Label header = new Label
                {
                    Text = "Picker",
                    FontSize = Device.GetNamedSize (NamedSize.Large, typeof(Label)),
                    HorizontalOptions = LayoutOptions.Center
                };

                Picker picker = new Picker
                {
                    Title = "Color",
                    VerticalOptions = LayoutOptions.CenterAndExpand
                };

                foreach (string colorName in nameToColor.Keys)
                {
                    picker.Items.Add(colorName);
                }

                // Create BoxView for displaying picked Color
                BoxView boxView = new BoxView
                {
                    WidthRequest = 150,
                    HeightRequest = 150,
                    HorizontalOptions = LayoutOptions.Center,
                    VerticalOptions = LayoutOptions.CenterAndExpand
                };

                picker.SelectedIndexChanged += (sender, args) =>
                    {
                        if (picker.SelectedIndex == -1)
                        {
                            boxView.Color = Color.Default;
                        }
                        else
                        {
                            string colorName = picker.Items[picker.SelectedIndex];
                            boxView.Color = nameToColor[colorName];
                        }
                    };

                // Accomodate iPhone status bar.
                this.Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 5);

                // Build the page.
                this.Content = new StackLayout
                {
                    Children =
                    {
                        header,
                        picker,
                        boxView
                    }
                };

            }
        }

Source : https://developer.xamarin.com/api/type/Xamarin.Forms.Picker/

Comments

0

For anyone that wants to bind a Picker to an ID (key) from a collection then the Item selected doesn't really give you want you want here, as you will get the object and not the ID that you really want. So my solution is a Converter, you change the object into the ID that you want. In the following solution I create a multivalue converter, pass the collection I'm using, the Id I'm binding too and the property name as a param. This way I can use reflection to find value I need, making this converter very reuseable.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Xamarin.Forms;

namespace Xamarin.UI.Converters.Multi
{
    public class PickerSelectorConverter : IMultiValueConverter
    {
        public object Convert(object[] value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null) return null;
            if (value[0] == null) return null;
            if (value[1] is not IEnumerable<object> collection) return null;
            if (parameter == null || parameter is not string param) return null;

            return collection.AsQueryable().FirstOrDefault(x => x.GetType().GetProperty(param).GetValue(x).ToString() == value[0].ToString());
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            if (value == null) return null;
            if (parameter == null || parameter is not string param) return null;

            return new object[2] { value.GetType().GetProperty(param).GetValue(value), null };
        }
    }
}

 <Picker ItemDisplayBinding="{Binding Name}"
         ItemsSource="{Binding Collection}">
         <Picker.SelectedItem>
                <MultiBinding Converter="{StaticResource PickerSelectorConverter}" ConverterParameter="Id">
                        <Binding Mode="TwoWay" Path="Id" />
                        <Binding Mode="OneWay" Path="Collection" />
                 </MultiBinding>
          </Picker.SelectedItem>
 </Picker>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.