djangojazz
djangojazz

Reputation: 13232

Update a ViewModel when an item in an observable collection is updated

Source code is here: https://github.com/djangojazz/BubbleUpExample

The problem is I am wanting an ObservableCollection of a ViewModel to invoke an update when I update a property of an item in that collection. I can update the data that it is bound to just fine, but the ViewModel that holds the collection is not updating nor is the UI seeing it.

public int Amount
{
  get { return _amount; }
  set
  {
    _amount = value;
    if (FakeRepo.Instance != null)
    {
      //The repo updates just fine, I need to somehow bubble this up to the 
      //collection's source that an item changed on it and do the updates there.
      FakeRepo.Instance.UpdateTotals();
      OnPropertyChanged("Trans");
    }
    OnPropertyChanged(nameof(Amount));
  }
}

I basically need the member to tell the collection where ever it is called: "Hey I updated you, take notice and tell the parent you are a part of. I am just ignorant of bubble up routines or call backs to achieve this and the limited threads I found were slightly different than what I am doing. I know it could possible be done in many ways but I am having no luck.

In essence I just want to see step three in the picture below without having to click on the column first.

enter image description here

Upvotes: 0

Views: 2004

Answers (2)

Danny
Danny

Reputation: 191

You should do two things to get it to work: first: you should refactor the RunningTotal property so it can raise the property changed event. Like so:

private int _runningTotal;
public int RunningTotal
{
    get => _runningTotal;
    set
    {
        if (value == _runningTotal)
            return;
        _runningTotal = value;
        OnPropertyChanged(nameof(RunningTotal));
    }
}

Second thing you should do is calling the UpdateTotals after you add a DummyTransaction to the Trans. An option could be to refactor the AddToTrans method in the FakeRepo

public void AddToTrans(int id, string desc, int amount)
{            
  Trans.Add(new DummyTransaction(id, desc, amount));
  UpdateTotals();
}

Upvotes: 1

jammerla
jammerla

Reputation: 36

Provided that your underlying items adhere to INotifyPropertyChanged, you can use an observable collection that will bubble up the property changed notification such as the following.

public class ItemObservableCollection<T> : ObservableCollection<T> where T : INotifyPropertyChanged
{
    public event EventHandler<ItemPropertyChangedEventArgs<T>> ItemPropertyChanged;


    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
    {
        base.OnCollectionChanged(args);
        if (args.NewItems != null)
            foreach (INotifyPropertyChanged item in args.NewItems)
                item.PropertyChanged += item_PropertyChanged;

        if (args.OldItems != null)
            foreach (INotifyPropertyChanged item in args.OldItems)
                item.PropertyChanged -= item_PropertyChanged;
    }

    private void OnItemPropertyChanged(T sender, PropertyChangedEventArgs args)
    {
        if (ItemPropertyChanged != null)
            ItemPropertyChanged(this, new ItemPropertyChangedEventArgs<T>(sender, args.PropertyName));
    }

    private void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        OnItemPropertyChanged((T)sender, e);
    } 
}

Upvotes: 2

Related Questions