如何在树结构中访问父对象

时间:2017-07-31 09:20:55

标签: c# data-structures uwp

我正在使用MVVM,它正常工作,除了一件事,访问父模型对象。

目标是直接访问任何模型对象的父对象,但我找不到一种方法来做到这一点。

例如:

祖父母

---父母

--- ---孩子们

--- --- ---孙子

我提到了一个孩子,但是我必须检查一些孩子和父母的属性。

目前,代码正在运行所有更高级别的对象,直到父亲的孙子孙女与我的孙子对象成功匹配,然后才能检查属性。 但是这在智能代码和效率方面有点令人作呕,与此无关,我不想为了幸运的比赛而运行我的所有数据。这是当前的错位,其他一些部分是通过LINQ完成的。

    var someChild = calledChild;
    foreach (Grandparent gParent in mainViewModel.SelectedEnvironment.GrandParents)
    {
        foreach (Parent parent in gParent.Parents)
        {
            foreach (Child child in parent.Children)
            {
                if (child.A == calledChild.A)
                {
                     // Match
                     System.Diagnostics.Debug.WriteLine("CalledChilds grandparent is " + gParent.Name);
                }
            }
        }
    }

模型在类中设置,其定义如下:

public class Parent : ObservableObject
{
    public const string NamePropertyName = "Name";
    private string _name;

    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            if (_name == value)
            {
                return;
            }
            _name = value;
            RaisePropertyChanged(NamePropertyName);
        }
    }

    public const string ChildrenPropertyName = "Children";
    private ObservableCollection<Child> _children;

    public ObservableCollection<Child> Children
    {
        get
        {
            return _children;
        }
        set
        {
            if (_children == value)
            {
                return;
            }
            _children = value;
            RaisePropertyChanged(ChildrenPropertyName);
        }
    }
}

模型保存在json文件中,并解析回模型的根对象类型以供使用。

我不能只添加新的参考资料&#34; Parent&#34;到了孩子&#34;对象,因为它会在循环中结束,因为这个概念限制。

获取引用而不是整个模型分支的副本会很棒。

有没有办法直接访问父对象?

谢谢大家!

1 个答案:

答案 0 :(得分:1)

最简单的方法是在子节点中存储对父节点的直接引用:

public class ParentNode
{
    private ObservableCollection<ChildNode> _children;
    public ParentNode()
    {
        _children = new ObservableCollection<ChildNode>();
        Children = new ReadOnlyObservableCollection<ChildNode>(_children);
    }
    public ReadOnlyObservableCollection<ChildNode> Children { get; }

    public void AddChild(ChildNode item)
    {
        if (item.Parent != null) throw new InvalidOperationException("Item is already added to another node");
        item.Parent = this;
        _children.Add(item);
    }
    public void RemoveChild(ChildNode item)
    {
        if (item.Parent != this) throw new InvalidOperationException("Item is not direct child of this node");
        item.Parent = null;
        _children.Remove(item);
    }
}

public class ChildNode
{
    public ParentNode Parent { get; internal set; }
}

要小心,因为这会引入循环引用 - 父引用子代,反之亦然。它违反了DRY原则,因为树的形状被定义了两次,你可能很容易失去同步(例如你将ChildNode.Parent属性设置为除了实际父级之外的其他属性)。

有办法解决它,但我认为你可以从这开始。