Обновление модели представления при обновлении элемента в наблюдаемой коллекции

Исходный код находится здесь: https://github.com/djangojazz/BubbleUpExample

Проблема в том, что я хочу, чтобы ObservableCollection ViewModel вызывал обновление, когда я обновляю свойство элемента в этой коллекции. Я могу обновить данные, к которым они привязаны, просто отлично, но ViewModel, который содержит коллекцию, не обновляется, и пользовательский интерфейс его не видит.

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

Мне в основном нужно, чтобы участник сказал коллекции, где она называется: "Эй, я обновил вас, обратите внимание и сообщите родителю, в чьей части вы участвуете. Я просто не знаю, какие подпрограммы всплывают или обратные вызовы, чтобы добиться этого, и ограниченный нити, которые я обнаружил, немного отличались от того, что я делаю. Я знаю, что это можно сделать разными способами, но мне не повезло.

По сути, я просто хочу увидеть третий шаг на рисунке ниже, не нажимая сначала на столбец.

2 ответа

Решение

При условии, что ваши базовые элементы придерживаются INotifyPropertyChanged, вы можете использовать наблюдаемую коллекцию, которая будет пузырить уведомление об изменении свойства, например, следующее.

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

Вы должны сделать две вещи, чтобы заставить его работать: во-первых: вы должны реорганизовать свойство RunningTotal, чтобы оно могло вызвать событие измененного свойства. Вот так:

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

Второе, что вы должны сделать, это позвонить UpdateTotals после добавления DummyTransaction к Trans, Одним из вариантов может быть рефакторинг AddToTrans метод в FakeRepo

public void AddToTrans(int id, string desc, int amount)
{            
  Trans.Add(new DummyTransaction(id, desc, amount));
  UpdateTotals();
}
Другие вопросы по тегам