fstam
fstam

Reputation: 699

How to update an ObservableCollection with a List and update only the changed values?

Edit: Turns out I was merging a list with the latest data from a rest API with the data in my GUI. All I really had to do was clear and refill my observablecollection. This post is basically an xy problem. I did not have the vocabulary to explain the problem I was facing.

I'm building an app with a Data class where I store all my data. In this class I have a List filled with objects. I have a Page with a ObservableCollection and a ListView. Currently when I update the ObservableCollection, I clear it and refill it with all the data from Data-class's List. When I do this, my ListView flickers. My guess is that completely rebuilding the ObservableCollection causes this, in combination with a custom ViewCell that is not the lightests. How could I go about updating only what I want? The list/o.collection can have diffrent sizes. The list/o.collection both store the same object.

What I tried:

List<csharp.Truck> favs = data.getFavoriteTrucks();
trucks.Clear();
foreach (csharp.Truck truck in favs)
    {
        trucks.Add(truck);
    }
}

Works but makes my ListView flicker.

Trying this now, its pretty bad code I think, it does update the list how I want it to but the listview does not get updated for some reason. Maybe I need to trigger a refresh?

List<csharp.Truck> all = data.getTrucks();
//if list sizes are not equal(excess/missing objects)
if (all.Count != trucks.Count)
{
    //excess object
    if (all.Count < trucks.Count)
    {
        trucks.Clear();
        foreach(csharp.Truck t in all)
        {
            trucks.Add(t);
        }
    }
    //object missing
    if(all.Count > trucks.Count)
    {
        foreach(csharp.Truck t in all)
        {
            if (!trucks.Contains(t))
            {
                trucks.Add(t);
            }
        }
    }
}//objects are now the same

//test if object is present but outdated(favorite property)
foreach(csharp.Truck t in trucks)
{
    if (t.isFavorite() != all[all.IndexOf(t)].isFavorite())
    {
        t.setFavorite(all[all.IndexOf(t)].isFavorite());
    }
}

Also let me know if this approach is not good practise in the first place.

Upvotes: 0

Views: 2361

Answers (1)

Yehor Hromadskyi
Yehor Hromadskyi

Reputation: 3388

If you want to update only some properties, you could implement in your model class INotifyPropertyChanged interface.

public class Model : INotifyPropertyChanged
{
    private string _myProperty;
    public string MyProperty
    {
        get { return _myProperty; }
        set
        {
            _myProperty = value;
            RaisePropertyChanged();
        }
    }

    #region INotifyPropertyChanged implementation

    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged([CallerMemberName]string propertyName = "")
    {
        Volatile.Read(ref PropertyChanged)?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion
}

And then if this property is binded to view, view will know, when you change it:

<Label Text="{Binding MyProperty}" />

Upvotes: 1

Related Questions