BindableProperty 未在 ViewModel 上更新
BindableProperty not updated on ViewModel
在 Xamarin.Forms 中,我实现了自定义 Picker
。
ItemsSource
设置正确。但是,当我更改所选项目时,它不会更新我的 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 the
ViewModel` 更新:
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);
未指定 defaultBindingMode
,BindingMode
设置为 OneWay
,这意味着绑定从源(您的视图模型)更新到目标(您的视图)。
这可以通过更改默认绑定模式来解决:
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"/>
除了将 Mode=TwoWay
添加到我的绑定之外,还必须更改我的选择器中的一些内容,以便它可以与我绑定到的实际对象一起使用。
Xamarin Picker
的 Items
属性 是一个 IList<string>
因为我的所有项目都作为字符串添加到它,所以它保持相同的索引值。
因此 ItemsSource 更改为 IList
:
public IList ItemsSource
{
get { return (IList)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
我还修改了 SelectedIndexChanged
方法,因此它不会从 Items
中检索项目,而是从 ItemsSource
中检索项目,在我的例子中是 IList<Category>
:
private void OnSelectedIndexChanged(object sender, EventArgs eventArgs)
{
if (SelectedIndex < 0 || SelectedIndex > Items.Count - 1)
{
SelectedItem = null;
}
else
{
SelectedItem = ItemsSource[SelectedIndex];
}
}
在我的 ViewModel
中,我不再将 ObservableCollection
用于我的 Categories
,而是将这些项目添加到 IList<Category>
。
ObservableCollection
没有用,因为当我的 BindablePicker
绑定到 ItemsSource
时,项目被添加到内部 IList<string>
。将项目添加到集合时,它不会更新。我现在更新整个 ItemSource
如果更改了项目。
在 Xamarin.Forms 中,我实现了自定义 Picker
。
ItemsSource
设置正确。但是,当我更改所选项目时,它不会更新我的 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 the
ViewModel` 更新:
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);
未指定 defaultBindingMode
,BindingMode
设置为 OneWay
,这意味着绑定从源(您的视图模型)更新到目标(您的视图)。
这可以通过更改默认绑定模式来解决:
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"/>
除了将 Mode=TwoWay
添加到我的绑定之外,还必须更改我的选择器中的一些内容,以便它可以与我绑定到的实际对象一起使用。
Xamarin Picker
的 Items
属性 是一个 IList<string>
因为我的所有项目都作为字符串添加到它,所以它保持相同的索引值。
因此 ItemsSource 更改为 IList
:
public IList ItemsSource
{
get { return (IList)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
我还修改了 SelectedIndexChanged
方法,因此它不会从 Items
中检索项目,而是从 ItemsSource
中检索项目,在我的例子中是 IList<Category>
:
private void OnSelectedIndexChanged(object sender, EventArgs eventArgs)
{
if (SelectedIndex < 0 || SelectedIndex > Items.Count - 1)
{
SelectedItem = null;
}
else
{
SelectedItem = ItemsSource[SelectedIndex];
}
}
在我的 ViewModel
中,我不再将 ObservableCollection
用于我的 Categories
,而是将这些项目添加到 IList<Category>
。
ObservableCollection
没有用,因为当我的 BindablePicker
绑定到 ItemsSource
时,项目被添加到内部 IList<string>
。将项目添加到集合时,它不会更新。我现在更新整个 ItemSource
如果更改了项目。