c# - BindablePicker 的 SelectedItem 在 MvvmCross + xamarin 表单中的 Bindable stackLayout 中不起作用

标签 c# asp.net-mvc xamarin.forms

View 模型:

    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>

可绑定(bind)选择器:

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 中获取值。

最佳答案

我有解决方案

< controls:BindablePicker ItemsSource="{Binding Values}"DisplayProperty="Name"Title="{Binding Name}"SelectedItem="{Binding Path=BindingContext.SelectedAttributeValue, Source={x:Reference Name=mypagename}} "/>

关于c# - BindablePicker 的 SelectedItem 在 MvvmCross + xamarin 表单中的 Bindable stackLayout 中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38910302/

相关文章:

c# - 在 .NET 中生成、显示和打印简单文档

.net - 将 API 与 MVC 项目分离

button - 如何设置按钮的大小Xamarin

xamarin.forms - Prism for Xamarin Forms - 从选项卡页导航

c# - 使用 Xamarin Forms 在 ContentResolver.Insert() 上获取编译错误以创建事件

c# - 在 A SYSTEM 上消耗几乎 100% CPU 的应用程序

c# - 下载数千个网页的最有效方法

c# - 是否可以编写使用 xamarin 表单(UI)和 Unity(3D 部分)开发的非游戏跨平台 3D 可视化移动应用程序?

c# - 在生产中隐藏 MVC 页面

asp.net-mvc - 如何在MVC WebGrid中显示行号