2015-05-25 51 views
3

在Xamarin.Forms中,我實現了一個自定義PickerItemsSource設置正確。但是,當我更改所選項目時,它不會更新我的ViewModel上的屬性。BindableProperty在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 to the更新ViewModel`:

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

回答

0

除了加入Mode=TwoWay我綁定不得不改變我的選擇器中有些東西,因此它可以與實際的對象我曾經有過一定要工作。

Xamarin PickerItems屬性是一個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我不再使用ObservableCollectionCategories但這些項目添加到IList<Category>

ObservableCollection沒有用,因爲當我的BindablePicker綁定到ItemsSource項目被添加到內部IList<string>。將項目添加到集合時,它不會被更新。如果項目更改,我現在更新整個ItemSource

3

在創建BindableProperty:

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

而不指定defaultBindingMode,所述BindingMode設爲OneWay,這意味着結合從源更新(您的視圖模型)到目標(您的視圖)。

這可以通過改變defaultBindingMode固定:

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

,或者,如果這是你想爲你的選擇器,但只希望在這個視圖更新源的默認值,你可以指定這個BindingMode只有綁定的實例:

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

我嘗試過這種方式,並沒有幫助所有它真的應該啓用這麼upvote。我注意到,當我從類型Category更改綁定屬性到它成功的對象時,它只是字符串值被推回來,所以我將在稍後處理並更新答案。 – JMan