xaml - ViewModel 上的 BindableProperty 未更新

标签 xaml data-binding xamarin.forms

在 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,因为它们只需要从“View”更新为 View 模型`:

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

最佳答案

创建 BindableProperty 时:

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

如果不指定 defaultBindingModeBindingMode 将设置为 OneWay,这意味着 Binding 从源(您的 View 模型)更新到目标(您的观点)。

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

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

或者,如果您希望选择器使用默认值,但只想在此 View 中更新源,则可以仅为此 Binding 实例指定 BindingMode:

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

关于xaml - ViewModel 上的 BindableProperty 未更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30444498/

相关文章:

xamarin.forms - 在 Xamarin 表单中调整事件指示器的大小

ipad - 无法安装应用程序 iPad,但它可以在 Xamarin.Forms 的 iPhone 中运行

c# - 将数字从字符串转换为整数,小数点以逗号或点分隔

wpf - "Prefix ' .... ' does not map to a namespace",设计师错误?

c# - MenuItem 可见性基于子菜单项状态

asp.net - 以声明方式访问转发器内的页面属性数据绑定(bind)

c# - 输入显示和隐藏密码

c# - TextBlock 作为复选框内容不显示

c# - 将自定义属性绑定(bind)到 TextBox UWP

Angular 2 : Difference between property binding with and without brackets?