对象层次结构中的层次结构更改通知

时间:2019-01-10 14:49:50

标签: c# .net wpf graphics drawingvisual

我在C#库中具有三种对象的递归层次结构。我们称它们为 Boxs 螺母螺栓可以包含其他螺母螺栓螺母螺栓显然不能包含任何东西。

假设每个 Box 具有 Box Nut Bolt ObservableCollections 。 >。每个 Nut Bolt 都实现 INotifyPropertyChanged

是否存在将可观察到的集合的更改或任何 Nut Bolt 的属性更改的通知传播到持有引用的对象的最佳实践,顶部?或您会建议的任何特定设计模式?

编辑:为了给这个问题提供一些背景知识,我领导了Chemistry for Word项目。您可以在左侧看到实时显示结构的组件。 Chem4Word Navigator 现在,不管您信不信,这目前通过数据绑定吸引了一切。在LHS上显示的每个分子都是ItemsControl。 (是的,我 am 将WPF与MVVM一起使用!)事实证明,这对于长期解决方案而言具有过多的开销和灵活性。因此,我回到了直接生成 DrawingVisuals 的过程。这种方法可以进行更精细的控制。 在我的原始示例中,螺母螺栓分子原子债券。如果添加,删除或更改了这些选项中的任何一个,则显示屏必须知道它以便可以更新。因为我已经实现了用于数据绑定的接口和对象,所以我想利用已有的代码。

3 个答案:

答案 0 :(得分:2)

我有一个类似的模型,可以快速访问有向无环图中的上游Node实例。 Node对其直系上级的引用很弱。 Node具有获取根的属性...,该属性试图返回其父级的根。如果没有父节点,则该节点为根。根源完全基于遏制。请注意,父节点不是集合...因为有时子节点甚至不在集合中。或多或少像...

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 ...我们的图可以具有的功能之一就是对其他图中的节点的引用。我们有一个节点解析器服务,它将获取那些其他节点。这些外观参考由一个标识值(GUIDLong)和一个关联的弱引用表示。这样,我们可以根据需要加载指定的节点,但不能将其保留超过必要的时间。解析器维护以这种方式解析的节点的LRU缓存。

如果此类已解析的引用需要解析其自己的父级,则存在类似的机制以允许从属节点解析其父级。即使是节点收集的子节点,也可以通过解析器服务进行延迟加载(尽管有些注释会通知我们的框架何时进行延迟加载,何时不进行延迟加载)。

因此,弱引用有助于解决所有这些偶然解决的情况。嗯...更准确地说,它们可以帮助我们避免在这种情况下搞乱垃圾收集。

在某些分析场景中,我们将弹出数十万个节点。我可以想象化学建模中的类似动力学。

答案 1 :(得分:1)

如果封装ObservableCollection的螺母和螺栓并且仅公开ReadOnlyObservableCollection,则可以使Add(Nut nut)方法(和另一个用于螺栓的方法)注册到添加的螺母NotifyPropertyChanged事件。

这样,您将在Box中知道孩子的属性何时发生更改并采取措施。

答案 2 :(得分:0)

您为什么不在更改通知中给父母打电话。类似于以下伪代码:

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