2016-11-12 2 views
0

Ich habe ein Xamarin.Forms-Projekt mit einem ListView mit einer ObservableCollection gefüllt. Die Klasse (Objekt), die jedes Objekt in der ObservableCollection darstellt, implementiert INotifyPropertyChanged. Eine Color-Eigenschaft wechselt in der Benutzeroberfläche gut, aber eine String-Eigenschaft verschwindet und kehrt nie zurück.INotifyPropertyChanged Xamarin Zeichenfolge Wert verschwindet einfach

Ich bekomme die Anfangswerte von einem Webservice, aber dann nur eine völlig statische Änderung der Werte, zum Debuggen und ich kann es immer noch nicht herausfinden.

An der Spitze der Klasse meines Content Ich habe diese:

public ObservableCollection<GroceryItem> oc; 

Nach meinem Webservice ich die Daten in der ObservableCollection mit den Daten setzte zurückgekehrt ist und dass machen, die Itemssource für die Listenansicht. So geht's:

lvGroceries.ItemsSource = oc; 

Alles funktioniert super.

Die 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> 

Die Klasse - 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)); 
    } 

} 

Der Click-Handler. Ich nehme ein Objekt aus der ObservableCollection und ändere die beiden Eigenschaften.

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"; 
     } 
    } 
} 

Die Farbe wechselt in der Benutzeroberfläche in Ordnung, aber der isNeeded String-Wert verschwindet auf dem ersten Abgriff und nie wieder erscheint

Ideen?

Antwort

0

Ein paar Probleme hier. Erste ist, dass Sie Ihre ObservableCollection Lauf machen müssen OnPropertyChanged() wenn es wie so geändert wurde:

private ObservableCollection<GroceryItem> _oc; 

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

Jetzt sollten Sie haben wirklich alles in einem Viewmodel, aber da Sie dies nicht tun, müssen Sie Ihre ContentPage als gesetzt die BindingContext aus dem Code-behind wie folgt aus:

public partial class MyGroceryPage : ContentPage { 

    public MyGroceryPage() { BindingContext = this; } 
} 

Sie müssen auch Ihre ObservableCollection zu Ihrem ListView.ItemSource statt zuweisen es verbindlich. Das sieht wie folgt aus:

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

Wenn Sie die oben tun und dann gehen Sie in Ihren Code hinter und führen lvGroceries.ItemsSource = oc; dann, dass die Bindung würde überschreiben, dass Sie in Ihrem XAML tat, so nicht das tun. Stattdessen, wenn Sie Daten von Ihrem Web-Service zu erhalten, würden Sie weisen Sie nur auf Ihre ObservableCollection vorhanden:

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

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

alle Versuchen dieser ersten und wenn Ihre Artikel noch nicht aktualisieren Sie könnten sie aus versuchen wollen zu entfernen Ihre ObservableCollection, Ändern der Eigenschaften, dann Hinzufügen von ihnen zurück in:

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

Ich musste alle Schritte tun. Anscheinend muss ich viel lernen. Der Remove-Edit-Replace-Code konnte nicht in der foreach-Schleife ausgeführt werden, da der oc mit der foreach verbunden war, also tat ich folgendes: 'code' var itemIndex = oc.IndexOf (g); oc.RemoveAt (itemIndex); // Bearbeiten Sie den Artikel oc.Insert (itemIndex, g); 'code' Dank tons @ hvaughan3 – pdschuller

+0

@pdschuller Kein Problem. Froh, dass es geholfen hat. Es dauerte eine ganze Weile, bis ich mich mit der Bindung und allem, was damit verbunden war, wohl fühlte. Und ja, ich bin auch auf das 'foreach'-Problem gestoßen, normalerweise kann ich' foreach (var gr in oc.ToList()) '(beachte die' ToList() '), was eine neue' List <> 'verursacht geschaffen werden, die dieses Problem umgehen, aber klingt, als ob du es herausgefunden hättest. – hvaughan3

Verwandte Themen