Xamarin表单 - picker selectedItem未触发

时间:2017-09-28 12:31:49

标签: xamarin.forms picker

以下示例正常(https://developer.xamarin.com/samples/xamarin-forms/UserInterface/BindablePicker/

当我尝试在我的代码中实现它时,没有设置为selectedItem引用的对象。选择器正在加载并选择数据,只是不更新​​对象。

以下是我正在使用的一些代码: XAML页面

 <Picker x:Name="testpicker" Title="Select a Service" ItemsSource="{Binding Services}, Mode=TwoWay}" ItemDisplayBinding="{Binding ServiceDescription}" SelectedItem="{Binding SelectedServiceName, Mode=TwoWay}" />

我在视图模型中有对象,但在选择选择器项时从不调用它。:

string selectedServiceName;
    public string SelectedServiceName
    {
        get { return selectedServiceName; }
        set
        {
            if (selectedServiceName != value)
            {
                selectedServiceName = value;
                PickerOnPropertyChanged();
                PickerOnPropertyChanged("SelectedService");
            }
        }
    }

当视图加载时,从控制器完成绑定....

  protected async override void OnAppearing()
    {

        base.OnAppearing();
        await viewModel.LoadPreferenceData();
        await viewModel.LoadServiceData();

        testpicker.SelectedIndex = 5;

    }

我还更新了基类以反映教程,我更改了名称。

你能看到任何明显的原因吗?如果需要,我很乐意提供更多代码。

2 个答案:

答案 0 :(得分:1)

错误是由于将选择器绑定到源的自定义类型。

ItemsSource="{Binding Services}

我没有使用字符串作为绑定对象,而是更改了类型:

public String SelectedServiceName 

对此:

public Service SelectedServiceName 

答案 1 :(得分:0)

创建自定义选择器并在您的代码中实现它为我工作尝试下面的代码:

public class CustomPicker : Picker
    {
        public CustomPicker()
        {
            SelectedIndexChanged += OnSelectedIndexChanged;
        }

        public static readonly BindableProperty SelectedItemProperty =
            BindableProperty.Create("SelectedItem", typeof(object), typeof(CustomPicker), null, BindingMode.TwoWay, null, OnSelectedItemChanged);

        public object SelectedItem
        {
            get { return GetValue(SelectedItemProperty); }
            set
            {
                SetValue(SelectedItemProperty, value);

                if (value != null &&  ItemsSource!=null && ItemsSource.Contains(value))
                    SelectedIndex = ItemsSource.IndexOf(value);
                else
                    SelectedIndex = -1;
            }
        }

        public static readonly BindableProperty ItemsSourceProperty =
            BindableProperty.Create("ItemsSource", typeof(IEnumerable), typeof(CustomPicker), null, BindingMode.TwoWay, null, OnItemsSourceChanged);

        public IList ItemsSource
        {
            get { return (IList)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }

        public static readonly BindableProperty DisplayPropertyProperty =
            BindableProperty.Create("DisplayProperty", typeof(string), typeof(CustomPicker), null, BindingMode.TwoWay, null, OnDisplayPropertyChanged);


        public string DisplayProperty
        {
            get { return (string)GetValue(DisplayPropertyProperty); }
            set { SetValue(DisplayPropertyProperty, value); }
        }
        private static void OnSelectedItemChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var picker = (CustomPicker)bindable;
            picker.SelectedItem = newValue;
            if (picker.ItemsSource != null && picker.SelectedItem != null)
            {
                var count = 0;
                foreach (var obj in picker.ItemsSource)
                {
                    if (obj == picker.SelectedItem)
                    {
                        picker.SelectedIndex = count;
                        break;
                    }
                    count++;
                }
            }
        }

        private static void OnDisplayPropertyChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var picker = (CustomPicker)bindable;
            picker.DisplayProperty = (string)newValue;
            LoadItemsAndSetSelected(bindable);
        }

        private static void OnItemsSourceChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var picker = (CustomPicker)bindable;
            picker.ItemsSource = (IList)newValue;

            var oc = newValue as INotifyCollectionChanged;

            if (oc != null)
            {
                oc.CollectionChanged += (a, b) =>
                {
                    LoadItemsAndSetSelected(bindable);
                };
            }

            LoadItemsAndSetSelected(bindable);
        }

        private static void LoadItemsAndSetSelected(BindableObject bindable)
        {
            var picker = (CustomPicker)bindable;

            if (picker.ItemsSource == null)
                return;

            var count = 0;

            foreach (var obj in picker.ItemsSource)
            {
                var value = string.Empty;
                if (picker.DisplayProperty != null)
                {
                    var prop = obj.GetType().GetRuntimeProperties().FirstOrDefault(p => string.Equals(p.Name, picker.DisplayProperty, StringComparison.OrdinalIgnoreCase));

                    if (prop != null)
                        value = prop.GetValue(obj).ToString();
                }
                else
                {
                    value = obj.ToString();
                }

                if (!picker.Items.Contains(value))
                {
                    picker.Items.Add(value);
                }

                if (picker.SelectedItem != null && picker.SelectedItem == obj)
                    picker.SelectedIndex = count;

                count++;
            }

            if (picker.ItemsSource.Count == picker.Items.Count - 1)
                picker.SelectedIndex++;
        }
        private void OnSelectedIndexChanged(object sender, EventArgs e)
        {
            if (SelectedIndex > -1)
            {
                SelectedItem = ItemsSource[SelectedIndex];
            }
        }
    }

Xaml代码

 <userControls:CustomPicker BackgroundColor="Transparent"  x:Name="testpicker" HorizontalOptions="FillAndExpand" ItemsSource="{Binding Services}" SelectedItem="{Binding SelectedServiceName}" DisplayProperty="{Binding ServiceDescription}" />

别忘了放入Xaml标题

xmlns:userControls="clr-namespace:MyNameSpace"