在MvvmCross + xamarin表单中,BindablePicker的SelectedItem不能在bindab

本文关键字:SelectedItem 不能 bindab BindablePicker MvvmCross xamarin 表单 | 更新日期: 2023-09-27 18:01:59

ViewModel:

    List<PictureModel> _pages;
    public List<PictureModel> Pages
    {
        get
        {
            return _pages;
        }
        set
        {
            _pages = value;
            RaisePropertyChanged(() => Pages);
            CurrentPage = Pages.FirstOrDefault();
        }
    }
    private AttributeValue _selectedAttributeValue;
    public AttributeValue SelectedAttributeValue
    {
        get { return _selectedAttributeValue; }
        set
        {
            _selectedAttributeValue = value;
            RaisePropertyChanged(() => SelectedAttributeValue);
            SelectedAttributeCommand.Execute(null);
        }
    }
    public ICommand SelectedAttributeCommand
    {
        get
        {
            //return new MvxCommand(() => ShowViewModel<ReviewsPageViewModel>());
            return new MvxCommand(() =>
            {
                ChangePresentation(new MvxClosePresentationHint(new ProductListPageViewModel()));
            });
        }
    }

我的XAML文件:

<controls:AwesomeWrappanel HorizontalOptions="CenterAndExpand"        Orientation="Horizontal" ItemsSource="{Binding ProductDeatil.ProductAttributes}" Spacing="10">
        <controls:AwesomeWrappanel.ItemTemplate>
                <DataTemplate>
                       <controls:BindablePicker ItemsSource="{Binding Values}" 
                         DisplayProperty="Name" Title="{Binding Name}" 
                         SelectedIndex="0" SelectedItem="{Binding 
                         SelectedAttributeValue, Mode=TwoWay}" />           
               </DataTemplate>
        </controls:AwesomeWrappanel.ItemTemplate>
</controls:AwesomeWrappanel>

BindablePicker:

public class BindablePicker : Picker
{
    public BindablePicker()
    {
        this.SelectedIndexChanged += OnSelectedIndexChanged;
    }

    public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create("SelectedItem", typeof(object), typeof(BindablePicker), null, BindingMode.TwoWay, null, new BindableProperty.BindingPropertyChangedDelegate(BindablePicker.OnSelectedItemChanged), null, null, null);
    public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create("ItemsSource", typeof(IEnumerable), typeof(BindablePicker), null, BindingMode.TwoWay, null, new BindableProperty.BindingPropertyChangedDelegate(BindablePicker.OnItemsSourceChanged), null, null, null);
    public static readonly BindableProperty DisplayPropertyProperty = BindableProperty.Create("DisplayProperty", typeof(string), typeof(BindablePicker), null, BindingMode.TwoWay, null, new BindableProperty.BindingPropertyChangedDelegate(BindablePicker.OnDisplayPropertyChanged), null, null, null);
    public IList ItemsSource
    {
        get { return (IList)base.GetValue(BindablePicker.ItemsSourceProperty); }
        set { base.SetValue(BindablePicker.ItemsSourceProperty, value); }
    }
    public object SelectedItem
    {
        get { return base.GetValue(BindablePicker.SelectedItemProperty); }
        set
        {
            base.SetValue(BindablePicker.SelectedItemProperty, value);
            if (ItemsSource.Contains(SelectedItem))
            {
                SelectedIndex = ItemsSource.IndexOf(SelectedItem);
            }
            else
            {
                SelectedIndex = -1;
            }
        }
    }
    public string DisplayProperty
    {
        get { return (string)base.GetValue(BindablePicker.DisplayPropertyProperty); }
        set { base.SetValue(BindablePicker.DisplayPropertyProperty, value); }
    }
    private void OnSelectedIndexChanged(object sender, EventArgs e)
    {
        this.SelectedItem = ItemsSource[SelectedIndex];
    }

    private static void OnSelectedItemChanged(BindableObject bindable, object oldValue, object newValue)
    {
        BindablePicker picker = (BindablePicker)bindable;
        picker.SelectedItem = newValue;
        if (picker.ItemsSource != null && picker.SelectedItem != null)
        {
            int count = 0;
            foreach (object obj in picker.ItemsSource)
            {
                if (obj == picker.SelectedItem)
                {
                    picker.SelectedIndex = count;
                    break;
                }
                count++;
            }
        }
    }
    private static void OnDisplayPropertyChanged(BindableObject bindable, object oldValue, object newValue)
    {
        BindablePicker picker = (BindablePicker)bindable;
        picker.DisplayProperty = (string)newValue;
        loadItemsAndSetSelected(bindable);
    }
    private static void OnItemsSourceChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var picker = (BindablePicker)bindable;
        picker.ItemsSource = (IList)newValue;
        var oc = newValue as INotifyCollectionChanged;
        if (oc != null && !PickerLookup.ContainsKey(oc))
        {
            oc.CollectionChanged += Oc_CollectionChanged;
            PickerLookup.Add(oc, new WeakReference(picker));
        }
        loadItemsAndSetSelected(bindable);
    }
    private static readonly Dictionary<INotifyCollectionChanged, WeakReference> PickerLookup = new Dictionary<INotifyCollectionChanged, WeakReference>();
    private static void Oc_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        var oc = (INotifyCollectionChanged)sender;
        if (e.Action == NotifyCollectionChangedAction.Add)
        {
            var picker = (BindablePicker)PickerLookup[oc].Target;
            foreach (var newItem in e.NewItems)
            {
                var value = string.Empty;
                if (picker.DisplayProperty != null)
                {
                    var prop = newItem.GetType().GetRuntimeProperties().FirstOrDefault(p => string.Equals(p.Name, picker.DisplayProperty, StringComparison.OrdinalIgnoreCase));
                    if (prop != null)
                        value = prop.GetValue(newItem).ToString();
                }
                else
                {
                    value = newItem.ToString();
                }
                picker.Items.Add(value);
            }
        }
        else if (e.Action == NotifyCollectionChangedAction.Remove)
        {
            var picker = (BindablePicker)PickerLookup[oc].Target;
            foreach (var newItem in e.OldItems)
            {
                var value = string.Empty;
                if (picker.DisplayProperty != null)
                {
                    var prop = newItem.GetType().GetRuntimeProperties().FirstOrDefault(p => string.Equals(p.Name, picker.DisplayProperty, StringComparison.OrdinalIgnoreCase));
                    if (prop != null)
                        value = prop.GetValue(newItem).ToString();
                }
                else
                {
                    value = newItem.ToString();
                }
                picker.Items.Remove(value);
            }
        }
    }
    static void loadItemsAndSetSelected(BindableObject bindable)
    {
        BindablePicker picker = (BindablePicker)bindable;
        if (picker.ItemsSource as IEnumerable != null)
        {
            int count = 0;
            foreach (object obj in (IEnumerable)picker.ItemsSource)
            {
                string 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();
                }
                picker.Items.Add(value);
                if (picker.SelectedItem != null)
                {
                    if (picker.SelectedItem == obj)
                    {
                        picker.SelectedIndex = count;
                    }
                }
                count++;
            }
        }
    }
}

这里SelectedItem="{Binding SelectedAttributeValue}"不工作,ViewModel没有得到值

在MvvmCross + xamarin表单中,BindablePicker的SelectedItem不能在bindab

我有办法了

& lt;控件:BindablePicker ItemsSource="{绑定值}" DisplayProperty="Name" Title="{绑定名称}" SelectedItem="{绑定路径=BindingContext. properties "SelectedAttributeValue, Source={x:Reference Name=mypagename}}"/>