【问题标题】:BindableProperty not updated on ViewModelViewModel 上的 BindableProperty 未更新
【发布时间】:2015-08-07 07:09:08
【问题描述】:

在 Xamarin.Forms 中,我实现了一个自定义 PickerItemsSource 设置正确。但是,当我更改所选项目时,它不会更新我的 ViewModel 上的属性。

BindablePicker:

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

    public static BindableProperty ItemsSourceProperty =
        BindableProperty.Create<BindablePicker, IEnumerable>(o => o.ItemsSource, default(IEnumerable), propertyChanged: OnItemsSourceChanged);

    public static BindableProperty SelectedItemProperty =
        BindableProperty.Create<BindablePicker, object>(o => o.SelectedItem, default(object), propertyChanged: OnSelectedItemChanged);


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

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

    private static void OnItemsSourceChanged(BindableObject bindable, IEnumerable oldvalue, IEnumerable newvalue)
    {
        var picker = bindable as BindablePicker;
        picker.Items.Clear();
        if (newvalue != null)
        {
            //now it works like "subscribe once" but you can improve
            foreach (var item in newvalue)
            {
                picker.Items.Add(item.ToString());
            }
        }
    }

    private void OnSelectedIndexChanged(object sender, EventArgs eventArgs)
    {
        if (SelectedIndex < 0 || SelectedIndex > Items.Count - 1)
        {
            SelectedItem = null;
        }
        else
        {
            SelectedItem = Items[SelectedIndex];
        }
    }
    private static void OnSelectedItemChanged(BindableObject bindable, object oldvalue, object newvalue)
    {
        var picker = bindable as BindablePicker;
        if (newvalue != null)
        {
            picker.SelectedIndex = picker.Items.IndexOf(newvalue.ToString());
        }
    }
}

Xaml页面:

<controls:BindablePicker Title="Category"
        ItemsSource="{Binding Categories}"
        SelectedItem="{Binding SelectedCategory}"
        Grid.Row="2"/>

ViewModel 属性没有在属性上实现NotifyPropertyChanged,因为它们只需要从 ´Viewto theViewModel` 更新:

public Category SelectedCategory { get; set; }
public ObservableCollection<Category> Categories { get; set; }

【问题讨论】:

    标签: xaml data-binding xamarin.forms


    【解决方案1】:

    创建 BindableProperty 时:

    public static BindableProperty SelectedItemProperty =
        BindableProperty.Create<BindablePicker, object>(o => o.SelectedItem, default(object), propertyChanged: OnSelectedItemChanged);
    

    没有指定defaultBindingModeBindingMode 设置为OneWay,这意味着绑定从源(您的视图模型)更新到目标(您的视图)。

    这可以通过更改 defaultBindingMode 来解决:

    public static BindableProperty SelectedItemProperty =
        BindableProperty.Create<BindablePicker, object>(o => o.SelectedItem, default(object), BindingMode.TwoWay, propertyChanged: OnSelectedItemChanged);
    

    或者,如果它是您希望选择器的默认值,但只想在此视图中更新源,您可以为该 Binding 实例指定 BindingMode:

    <controls:BindablePicker Title="Category"
        ItemsSource="{Binding Categories}"
        SelectedItem="{Binding SelectedCategory, Mode=TwoWay}"
        Grid.Row="2"/>
    

    【讨论】:

    • 我已经尝试过了,但没有任何帮助,尽管它确实应该启用,所以请点赞。我确实注意到,当我将绑定属性从类别类型更改为对象时它确实成功了,它只是被推回的字符串值,所以我稍后会处理它并更新答案。
    【解决方案2】:

    除了将Mode=TwoWay 添加到我的绑定之外,还必须更改我的选择器中的一些内容,以便它可以与我绑定到的实际对象一起使用。

    Xamarin PickerItems 属性是 IList&lt;string&gt; 因为我的所有项目都作为字符串添加到其中,所以它保持相同的索引值。

    因此将 ItemsSource 更改为 IList:

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

    我还修改了SelectedIndexChanged方法,因此它不会从Items 而是从ItemsSource 检索项目,在我的情况下是IList&lt;Category&gt;

    private void OnSelectedIndexChanged(object sender, EventArgs eventArgs)
        {
            if (SelectedIndex < 0 || SelectedIndex > Items.Count - 1)
            {
                SelectedItem = null;
            }
            else
            {
                SelectedItem = ItemsSource[SelectedIndex];
            }
        }
    

    在我的ViewModel 中,我不再将ObservableCollection 用于我的Categories,而是将这些项目添加到IList&lt;Category&gt;

    ObservableCollection 没有用,因为当我的 BindablePicker 绑定到 ItemsSource 时,这些项目被添加到内部 IList&lt;string&gt;。将项目添加到集合时,它不会被更新。我现在更新整个ItemSource如果项目被更改。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-14
      • 2023-04-03
      • 1970-01-01
      • 2018-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多