2016-11-12 56 views
0

我有一個Xamarin.Forms項目與一個ListView填充ObservableCollection。作爲ObservableCollection中每個項目的類(對象)實現INotifyPropertyChanged。 Color屬性在用戶界面中正常切換,但字符串屬性消失並且永不返回。INotifyPropertyChanged Xamarin字符串值只是消失

我從web服務獲得初始值,但只是做一個完全靜態的值的變化,用於調試,我仍然無法弄清楚。

在我ContentPage類的頂部我有這樣的:

public ObservableCollection<GroceryItem> oc; 

後我的web服務已與我把數據的的ObservableCollection返回的數據並作出,該的ItemsSource爲ListView。像這樣:

lvGroceries.ItemsSource = oc; 

這一切都很好。

的XAML

<ListView x:Name="lvGroceries" ItemTapped="GroceryPdsItemTapped" >    
    <ListView.ItemTemplate > 
    <DataTemplate> 
     <ViewCell>    
     <AbsoluteLayout VerticalOptions="Fill"> 
      <Label Text="{Binding GroceryName}" AbsoluteLayout.LayoutBounds="0,0,200,40" ></Label> 
      <Label Text="{Binding strHomeLoc}" AbsoluteLayout.LayoutBounds="200,0,100,40" ></Label> 
      <Label Text="{Binding isNeeded}" AbsoluteLayout.LayoutBounds="300,0,50,40" ></Label>     
      <Label Text="someText" BackgroundColor="{Binding myBackgroundColor}" AbsoluteLayout.LayoutBounds="350,0,50,40" ></Label> 
     </AbsoluteLayout>   
     </ViewCell> 
    </DataTemplate> 
    </ListView.ItemTemplate> 
</ListView> 

類 - GroceryItem

public class GroceryItem : INotifyPropertyChanged 
{ 
    public GroceryItem() { } 
    public event PropertyChangedEventHandler PropertyChanged; 

    private string privateIsNeeded; 
    public string isNeeded 
    { 
     get { return privateIsNeeded; } 
     set 
     { 
      privateIsNeeded = value; 
      OnPropertyChanged(); 
     } 
    } 

    private Color theColor; 
    public Color myBackgroundColor 
    { 
     get { return theColor; } 
     set 
     { 
      theColor = value; 
      OnPropertyChanged(); 
     } 
    } 

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 

} 

單擊處理程序。我從ObservableCollection中獲取一個項目並更改這兩個屬性。

public void GroceryPdsItemTapped(object obj, ItemTappedEventArgs e) 
{ 
    if (e.Item == null) 
    { 
     return; 
    } 
    var g = ((GroceryItem)e.Item); 
    foreach (var gr in oc) 
    { 
     if (gr.GroceryId == "27769") 
     { // the UI changes because the myBackgroundColor property in the GroceryItem class is watching for a value change 
      gr.myBackgroundColor = (gr.myBackgroundColor == Color.Yellow) ? Color.Blue : Color.Yellow; 
      gr.isNeeded = (gr.isNeeded == "true" || gr.isNeeded == "blah" || gr.isNeeded == "false") ? "notblah" : "blah"; 
     } 
    } 
} 

顏色切換優良的UI,但isNeeded字符串值消失的第一次敲擊和永不再出現

想法?

回答

0

這裏有一些問題。首先,你需要讓你的ObservableCollection運行OnPropertyChanged()時,它已經改變了,像這樣:

private ObservableCollection<GroceryItem> _oc; 

public ObservableCollection<GroceryItem> oc { 
    get { return _oc ?? (_oc = new ObservableCollection<GroceryItem>()); } 
    set { 
     if(_oc != value) { 
      _oc = value; 
      OnPropertyChanged(); 
     } 
    } 
} 

現在你要真有這一切在一個視圖模型,但既然你不這樣做,你需要設置你的ContentPage爲從內部代碼隱藏BindingContext這樣的:

public partial class MyGroceryPage : ContentPage { 

    public MyGroceryPage() { BindingContext = this; } 
} 

您還需要分配給它的有約束力的ObservableCollectionListView.ItemSource代替。這看起來是這樣的:

<ListView ItemSource="{Binding oc}"/> 

如果你做到上面,然後你進入後面的代碼並執行lvGroceries.ItemsSource = oc;那麼這將覆蓋綁定您在XAML一樣,所以做。相反,當您從網絡服務中獲取數據,你只需將其分配給現有的ObservableCollection

public async Task GetGroceryData() { 
    List<GroceryItem> myData = await GroceryService.GetGroceriesAsync(); 

    oc = new ObservableCollection<GroceryItem>(myData); 
} 

嘗試所有的第一,如果你的項目,仍沒有更新,你可能會想嘗試從消除他們的ObservableCollection,更改屬性,然後將它們添加回來:

public void GroceryPdsItemTapped(object obj, ItemTappedEventArgs e) { 

    if (e.Item == null) { return; } 

    var g = ((GroceryItem)e.Item); 

    foreach (var gr in oc.ToList()) { 

     if (gr.GroceryId == "27769") { // the UI changes because the myBackgroundColor property in the GroceryItem class is watching for a value change 
      oc.Remove(gr); 
      gr.myBackgroundColor = (gr.myBackgroundColor == Color.Yellow) ? Color.Blue : Color.Yellow; 
      gr.isNeeded = (gr.isNeeded == "true" || gr.isNeeded == "blah" || gr.isNeeded == "false") ? "notblah" : "blah"; 
      oc.Add(gr); 
     } 
    } 
} 
+0

我必須執行所有步驟。顯然,我有很多東西需要學習。 刪除 - 編輯 - 替換代碼無法在foreach循環中完成,因爲oc被捆綁在foreach中,所以我這樣做了: 'code' var itemIndex = oc.IndexOf(g); oc.RemoveAt(itemIndex); //編輯項目 oc.Insert(itemIndex,g); 'code' Thanks tons @ hvaughan3 – pdschuller

+0

@pdschuller沒問題。很高興幫助。花了我相當長的一段時間,以便對綁定和涉及它的一切感到滿意。並且,我也遇到了'foreach'問題,通常我可以做'foreach(var gr in oc.ToList())'(注意'ToList()'),這會導致一個新的'List <>'被創造出來解決這個問題,但聽起來像你想出來的。 – hvaughan3