简体   繁体   中英

Xamarin forms set Picker SelectedItem

I am working with a xamarin Forms. I am using Picker for DropDownList.

How can I set selectedItem to Picker?

My code

<Picker x:Name="VendorName" Title="Select" ItemDisplayBinding="{Binding VendorName}" SelectedItem="{Binding VendorName}" Style="{StaticResource PickerStyle}"></Picker>

and server side code is

Device.BeginInvokeOnMainThread(() =>
{
VendorName.ItemsSource = VendorList;
});

var currentVendor = new List<Vendor>();
currentVendor.Add(new Vendor { VendorID = "111", VendorName = "aaaa" });

VendorName.SelectedItem = currentVendor;

This may not be the most efficient but you could loop to find the index and set that way.

for (int x = 0; x <  VendorList.Count; x++)
        {
            if (VendorList[x].VendorName == currentVendor .VendorName )
            {
                VendorName.SelectedIndex = x;
            }
        }

After adding all values as list in Picker

just treat with it as an array

so if you want to set selected item just set selected item index

currentVendor.SelectedIndex = 0;

zero means you make selected item is the first one you added to Picker

If you are using MVVM, and want to set SelectedItem from the view model, things get tricky. There seems to be a bug in Xamarin that prevents us from using SelectedItem with a two way binding. More info: Xamarin Forms ListView SelectedItem Binding Issue and https://xamarin.github.io/bugzilla-archives/58/58451/bug.html .

Luckily, we can easily write our own Picker .

    public class TwoWayPicker : Picker
    {
        public TwoWayPicker()
        {
            SelectedIndexChanged += (sender, e) => SelectedItem = ItemsSource[SelectedIndex];
        }

        public static new readonly BindableProperty SelectedItemProperty = BindableProperty.Create(
            nameof(SelectedItem), typeof(object), typeof(TwoWayPicker), null, BindingMode.TwoWay, propertyChanged: OnSelectedItemChanged);
        public new object SelectedItem
        {
            get => GetValue(SelectedItemProperty);
            set => SetValue(SelectedItemProperty, value);
        }
        private static void OnSelectedItemChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var control = (TwoWayPicker)bindable;
            control.SetNewValue(newValue);
        }
        private void SetNewValue(object newValue)
        {
            if (newValue == null)
            {
                return;
            }
            for(int i = 0; i < ItemsSource.Count; i++)
            {
                if (ItemsSource[i].Equals(newValue))
                {
                    SelectedIndex = i;
                    return;
                }
            }
        }
    }

Because is uses the same SelectedItem property, it is a drop-in replacement for Picker .

Note that if you want value equality rather than reference equality for the item class, you'll also need to override Equals like this:

        public override bool Equals(object obj)
        {
            var other = obj as YourClass;
            if (other == null)
            {
                return false;
            }
            else
            {
                return other.SomeValue == SomeValue; // implement your own
            }
        }

If you define the item class as a record instead of a class then it can select the item programmatically using the SelectedItem property.

In your case change

public class Vendor  { // your class properties }

to

public record Vendor  { // your class properties }

This will now work

VendorName.SelectedItem = currentVendor;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM