简体   繁体   中英

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.

在此处输入图片说明

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

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();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM