Иерархические уведомления об изменениях в иерархии объектов - PullRequest
0 голосов
/ 10 января 2019

У меня есть рекурсивная иерархия трех типов объектов в библиотеке C #. Давайте назовем их Ящики , Гайки и Болты . Коробки могут содержать другие Коробки или Гайки и Болты . Гайки и Болты явно не могут содержать ничего.

Предположим, что каждая коробка имеет ObservableCollections из коробка , гайка и болт . Каждый Гайка и Болт реализует INotifyPropertyChanged .

Существует ли принятая передовая практика для распространения уведомлений об изменениях в наблюдаемых коллекциях или изменениях свойств на любом гайке или болте для объекта, который содержит ссылку на самый верхний Box ? Или какие-то конкретные шаблоны дизайна вы бы порекомендовали?

РЕДАКТИРОВАТЬ : чтобы дать некоторое представление об этой проблеме, я возглавляю проект Chemistry for Word . Вы можете увидеть компонент, который отображает структуры в режиме реального времени слева. Chem4Word Navigator Теперь, хотите верьте, хотите нет, но в настоящее время все проходит через привязку данных. Каждая из этих молекул, отображаемая на LHS, представляет собой ItemsControl. (И да, я использую WPF с MVVM!) Это оказалось слишком много накладных расходов и отсутствие гибкости для долгосрочного решения. Итак, я вернулся к генерации DrawingVisuals напрямую. Такой подход позволяет гораздо более точный контроль. Коробки , Гайки и Болты в моем исходном примере: Молекулы , Атомы и Связи . Если какие-либо из них будут добавлены, удалены или изменены, то дисплей должен знать об этом, чтобы он мог обновляться. Поскольку я уже реализовал интерфейсы и объекты для привязки данных, я хочу использовать код, который у меня уже есть.

Ответы [ 3 ]

0 голосов
/ 10 января 2019

Если вы инкапсулируете свои ObservableCollection гаек и болтов и только обнародуете ReadOnlyObservableCollection, вы можете создать метод Add(Nut nut) (и еще один для болтов), который регистрируется в добавленном событии Nut NotifyPropertyChanged.

Таким образом, в Box вы узнаете, когда свойство ребенка изменилось, и начнете действовать.

0 голосов
/ 11 января 2019

У меня была похожая модель с быстрым доступом к вышестоящим экземплярам Node в ориентированных ациклических графах. Node имеет слабую ссылку на своего непосредственного родителя. Node имеет свойство для получения Root ..., которое пытается вернуть Root своего родителя. Если нет родителя, то этот узел является корнем. Корень основывается исключительно на сдерживании. Обратите внимание, что родительский элемент не является коллекцией ... потому что иногда дочерний узел отсутствует даже в коллекции. Что-то более или менее похожее ...

public abstract class Node
{
  WeakReference<Node> parent;

  public Node Root
  {
    get { return Parent?.Root ?? this; }
  }

  public Node Parent
  {
    get
    {
      if ( parent != null )
      {
        if ( parent.TryGetTarget( out Node parentNode ) )
        {
          return parentNode;
        }
      }
      return this;
    }
    internal set { /*...*/ } //--> if you're brave...
  }
}

Редактировать

Относительно WeakReferences ... одна из вещей, которую могут иметь наши графы, это ссылки на узлы в других графах. У нас есть служба распознавания узлов, которая будет извлекать эти другие узлы. Эти внешние ссылки представлены значением идентичности (GUID или Long) и связанной слабой ссылкой. Таким образом, мы можем загрузить указанный узел по мере необходимости, но не хранить его дольше, чем необходимо. Средство распознавания поддерживает кэш LRU узлов, разрешенных таким образом.

Если такая разрешенная ссылка должна разрешать своего родителя, существует аналогичный механизм, позволяющий зависимому узлу разрешать своего родителя. Даже собранные дочерние узлы узла могут быть лениво загружены через службу распознавания (хотя есть аннотации, которые сообщают нашей платформе, когда выполнять отложенную загрузку, а когда нет).

Итак, слабые ссылки помогают во всех этих случайно разрешенных сценариях. Э-э ... точнее, они помогают нам не портить сбор мусора в таких сценариях.

В некоторых аналитических сценариях у нас появляются и появляются сотни тысяч узлов. Я мог представить аналогичную динамику в химическом моделировании.

0 голосов
/ 10 января 2019

Почему бы вам не позвонить родителю в уведомлении об изменении. Что-то вроде следующего псевдокода:

Bolt()
{
    NotifyPropertyChanged(property)
    {
         PropertyChanged(this, property);
    }

    ChildNutPropertyChanged(Nut child, property)
    {
         PropertyChanged(this, child + property);
    }
}


Nut(Bolt parentBolt)
{ 
    parent = parentBolt;

    NotifyPropertyChanged(property)
    {
         PropertyChanged(this, property);
         parent.NotifyPropertyChanged(this, property);
    }
}
...