简体   繁体   中英

How to Create a Class That Can Have Parent and Child Relationship

I have seen quite a few articles on here about my question but none really answer what I am asking. I am creating a class of my Branch objects that you can envision as just like the TreeNode objects of the TreeView control. Each Branch can have any number of Branch children below (and therefore above) it. Here is my rather simple class:

public class Branch {
    public string Name { get; set; }
    public string Link { get; set; }
    public Branch Parent { get; private set; }
    public List<Branch> Children { get; set; }

    internal Branch(string Name, string Link) {
        this.Name = Name;
        this.Link = Link;
        this.Children = new List<Branch>();
    } // Branch - Constructor - Overload

    internal Branch(string Name, string Link, List<Branch> Children) {
        this.Name = Name;
        this.Link = Link;
        this.Children = Children;

        this.Children.ForEach(delegate(Branch branch) {
            branch.Parent = this;
        });
    } // Branch - Constructor - Overload

    public bool HasChildren {
        get { return this.Children.Count > 0; }
    } // HasChildren - Property - ReadOnly

    public string Path {
        get {
            string Result = "";

            Branch parent = this;
            while (parent != null) {
                Result = string.Format("{0}/{1}", parent.Name, Result);
                parent = parent.Parent;
            } // while stepping up the tree

            return string.IsNullOrWhiteSpace(Result) ? "" : Result.Substring(0, Result.Length - 1);
        } // get
    } // Path - Property - ReadOnly

This works GREAT if I Add children at the time of instantiation like the following:

List<Branch> Branches = new List<Branch>() {
    new Branch("First", "#"),
    new Branch("Second", "#"),
    new Branch("Third", "#", new List<Branch>() {
        new Branch("ThirdSub1", "#"),
        new Branch("ThirdSub2", "#")
    }),
    new Branch("Fourth", "#"),
    new Branch("Fifth", "#"),
    new Branch("Sixth", "#", new List<Branch>() {
        new Branch("SixthSub1", "#"),
        new Branch("SixthSub2", "#", new List<Branch>() {
            new Branch("SixthSub2Sub1", "#"),
            new Branch("SixthSub2Sub2", "#"),
            new Branch("SixthSub2Sub3", "#", new List<Branch>() {
                new Branch("Deep Deep Deep Undercover", "#"),
            }),
        }),
    }),
    new Branch("Seventh", "#"),
    new Branch("Eighth", "#"),
};

But if I do the following:

List<Branch> Branches = new List<Branch>();
Branch Test = Branches.Add(new Branch("Something", ""));
Test.Children.Add(new Branch("Child Here", ""));

The "Child Here" node does NOT have a Parent associated with it. Thus it is broken and of course the Path property doesn't work property.

I thought I could override the List's Add method but that is not allowed. What is the best way to handle this? Currently I am not creating my own Collection Class like MyBranches, which I like, but if there is a way of doing what I need while implementing IList or ISet or Collection, then I am willing to do so. But please provide an example.

Thanks!

Just for people in the future looking for this same solution, here is the full class:

public class Branch {
    public string Name { get; set; }
    public string Link { get; set; }
    public Branch Parent { get; set; }
    public TreeBranches Children { get; private set; }

    internal Branch(string Name, string Link) {
        this.Name = Name;
        this.Link = Link;
        this.Children = new TreeBranches(this);
    } // Branch - Constructor - Overload

    internal Branch(string Name, string Link, TreeBranches Children) {
        this.Name = Name;
        this.Link = Link;
        this.Children = Children;

        this.Children.ToList().ForEach(delegate(Branch branch) {
            branch.Parent = this;
        });
    } // Branch - Constructor - Overload

    /// <summary>
    /// Returns a boolean indicating if the given Branch has any child Branches.
    /// </summary>
    public bool HasChildren {
        get { return this.Children.Count > 0; }
    } // HasChildren - Property - ReadOnly

    /// <summary>
    /// Gets the path from the oldest ancestor to the current Branch.
    /// </summary>
    public string Path {
        get {
            string Result = "";

            Branch parent = this;
            while (parent != null) {
                Result = string.Format("{0}/{1}", parent.Name, Result);
                parent = parent.Parent;
            } // while stepping up the tree

            return string.IsNullOrWhiteSpace(Result) ? "" : Result.Substring(0, Result.Length - 1);
        } // get
    } // Path - Property - ReadOnly

} // Branch - Class

public class TreeBranches : IList<Branch> {
    private List<Branch> branches = new List<Branch>();
    private Branch owner;

    public TreeBranches() {
        this.owner = null;
    }

    public TreeBranches(Branch owner) {
        this.owner = owner;
    }

    public void Add(Branch branch) {
        branch.Parent = this.owner;
        this.branches.Add(branch);
    }

    #region Standard IList Method Implementation

    IEnumerator<Branch> IEnumerable<Branch>.GetEnumerator() { return this.branches.GetEnumerator(); }
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this.branches.GetEnumerator(); }
    public int IndexOf(Branch item) { return this.branches.IndexOf(item); }
    public void Insert(int index, Branch item) { this.branches.Insert(index, item); }
    public void RemoveAt(int index) { this.branches.RemoveAt(index); }
    public Branch this[int index] {
        get { return this.branches[index]; }
        set { this.branches[index] = value; }
    }

    public void Clear() { this.branches.Clear(); }
    public bool Contains(Branch item) { return this.branches.Contains(item); }
    public void CopyTo(Branch[] array, int arrayIndex) { this.branches.CopyTo(array, arrayIndex); }
    public int Count { get { return this.branches.Count(); } }
    public bool IsReadOnly { get { return this.IsReadOnly; } }
    public bool Remove(Branch item) { return this.branches.Remove(item); }

    #endregion Standard IList Method Implementation
} // TreeBranches - Class

You can derive from Collection<T> instead of List<T> , List<T> is faster, and is optimized for performance, but Collection<T> is more extensible and allows you to override Add() and others.

If performance is not an issue, then use Collection<T> , and if performance is an issue than use Reed's example of containing a List<T> in your own class.

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