Filling Winforms TreeView correctly

This is my data, I'm showing it in JSON format because it's easier to post and read. The data is actually a List returned from a DB.
[
    {"seqnbr":27,  "treelevel":1, "application":"Front",         "lrflag":null, "price":0.0,    "interchangenumber":null,           "parentlevel": 0},
    {"seqnbr":28,  "treelevel":2, "application":"V-Series",      "lrflag":null, "price":0.0,    "interchangenumber":null,           "parentlevel": 1},
    {"seqnbr":29,  "treelevel":3, "application":"opt J56",       "lrflag":null, "price":0.0,    "interchangenumber":null,           "parentlevel": 2},
    {"seqnbr":30,  "treelevel":4, "application":"R.",            "lrflag":"R",  "price":693.00, "interchangenumber":"536-01132AR",  "parentlevel": 3},
    {"seqnbr":31,  "treelevel":4, "application":"L.",            "lrflag":"L",  "price":693.00, "interchangenumber":"536-01133AL",  "parentlevel": 3},
    {"seqnbr":32,  "treelevel":3, "application":"opt J63",       "lrflag":null, "price":0.0,    "interchangenumber":null,           "parentlevel": 2},
    {"seqnbr":33,  "treelevel":4, "application":"R.",            "lrflag":"R",  "price":0.0,    "interchangenumber":"536-01130R",   "parentlevel": 3},
    {"seqnbr":34,  "treelevel":4, "application":"L.",            "lrflag":"L",  "price":0.0,    "interchangenumber":"536-01131L",   "parentlevel": 3},
    {"seqnbr":35,  "treelevel":2, "application":"exc. V-Series", "lrflag":null, "price":0.0,    "interchangenumber":null,           "parentlevel": 1},
    {"seqnbr":36,  "treelevel":3, "application":"opt JE5",       "lrflag":null, "price":0.0,    "interchangenumber":null,           "parentlevel": 2},
    {"seqnbr":37,  "treelevel":4, "application":"AWD",           "lrflag":null, "price":0.0,    "interchangenumber":null,           "parentlevel": 3},
    {"seqnbr":38,  "treelevel":5, "application":"R.",            "lrflag":null, "price":0.0,    "interchangenumber":"536-01142",    "parentlevel": 4},
    {"seqnbr":39,  "treelevel":5, "application":"L.",            "lrflag":null, "price":0.0,    "interchangenumber":"536-01143",    "parentlevel": 4},
    {"seqnbr":40,  "treelevel":4, "application":"RWD",           "lrflag":null, "price":0.0,    "interchangenumber":null,           "parentlevel": 3},
    {"seqnbr":41,  "treelevel":5, "application":"R.",            "lrflag":null, "price":0.0,    "interchangenumber":"536-01143",    "parentlevel": 4},
    {"seqnbr":42,  "treelevel":5, "application":"L.",            "lrflag":null, "price":0.0,    "interchangenumber":"536-01142",    "parentlevel": 4},
    {"seqnbr":43,  "treelevel":3, "application":"opt J55",       "lrflag":null, "price":0.0,    "interchangenumber":null,           "parentlevel": 2},
    {"seqnbr":44,  "treelevel":4, "application":"AWD",           "lrflag":null, "price":0.0,    "interchangenumber":null,           "parentlevel": 3},
    {"seqnbr":45,  "treelevel":5, "application":"R.",            "lrflag":null, "price":0.0,    "interchangenumber":"536-01036",    "parentlevel": 4},
    {"seqnbr":46,  "treelevel":5, "application":"L.",            "lrflag":null, "price":0.0,    "interchangenumber":"536-01037",    "parentlevel": 4},
    {"seqnbr":47,  "treelevel":4, "application":"RWD",           "lrflag":null, "price":0.0,    "interchangenumber":null,           "parentlevel": 3},
    {"seqnbr":48,  "treelevel":5, "application":"R.",            "lrflag":null, "price":0.0,    "interchangenumber":"536-01037",    "parentlevel": 4},
    {"seqnbr":49,  "treelevel":5, "application":"L.",            "lrflag":null, "price":0.0,    "interchangenumber":"536-01036",    "parentlevel": 4},
    {"seqnbr":260, "treelevel":1, "application":"Rear",          "lrflag":null, "price":0.0,    "interchangenumber":null,           "parentlevel": 0},
    {"seqnbr":261, "treelevel":2, "application":"Base",          "lrflag":null, "price":0.0,    "interchangenumber":null,           "parentlevel": 1},
    {"seqnbr":262, "treelevel":3, "application":"opt JE5",       "lrflag":null, "price":0.0,    "interchangenumber":null,           "parentlevel": 2},
    {"seqnbr":263, "treelevel":4, "application":"R.",            "lrflag":"R",  "price":0.0,    "interchangenumber":"536-01038R",   "parentlevel": 3},
    {"seqnbr":264, "treelevel":4, "application":"L.",            "lrflag":"L",  "price":0.0,    "interchangenumber":"536-01039L",   "parentlevel": 3},
    {"seqnbr":265, "treelevel":3, "application":"opt J55",       "lrflag":null, "price":0.0,    "interchangenumber":null,           "parentlevel": 2},
    {"seqnbr":266, "treelevel":4, "application":"R.",            "lrflag":"R",  "price":0.0,    "interchangenumber":"536-01042R",   "parentlevel": 3},
    {"seqnbr":267, "treelevel":4, "application":"L.",            "lrflag":"L",  "price":0.0,    "interchangenumber":"536-01043L",   "parentlevel": 3},
    {"seqnbr":268, "treelevel":2, "application":"V-Series",      "lrflag":null, "price":0.0,    "interchangenumber":null,           "parentlevel": 1},
    {"seqnbr":269, "treelevel":3, "application":"R.",            "lrflag":"R",  "price":403.00, "interchangenumber":"536-01134AR",  "parentlevel": 2},
    {"seqnbr":270, "treelevel":3, "application":"L.",            "lrflag":"L",  "price":466.00, "interchangenumber":"536-01135AL",  "parentlevel": 2}
]

Open in new window

This is how it should be presented in a Winforms Treeview:
Front
    V-Series
        opt J56
            R.
            L.
        opt J63
            R.
            L.      
    exc. V-Series
        opt JE5
            AWD
                R.
                L.
            RWD
                R.
                L.
        opt J55
            AWD
                R.
                L.
            RWD
                R.
                L.
Rear
    Base
        opt JE5
            R.
            L.
        opt J55
            R.
            L.
    V-Series
        R.
        L.

Open in new window

I have tried a number of different ways to do this but can't wrap my head around getting the node levels correct.

Here was my first attempt:
    string price = "";
    string application = "";
    string lrflag = "";
    string interchangenumber = "";
    foreach (indexlistapp a in data)
    {
        treelevel = a.treelevel;
        application = a.application;
        lrflag = a.lrflag;
        interchangenumber = a.interchangenumber;
        if(a.price > 0) 
        {
            price = string.Concat("PRICE:$", a.price.ToString(), " ");
        }
        if(treelevel == 1)
        {
            TreeNode treeNode = new TreeNode(String.Concat(application, lrflag, " ", price, "IC:", interchangenumber));
            tvResults.Nodes.Add(treeNode);
            tvResults.SelectedNode = treeNode;
        } 
        else 
        {
            TreeNode treeNode = new TreeNode(String.Concat(application, lrflag, " ", price, "IC:", interchangenumber));
            tvResults.SelectedNode.Nodes.Add(treeNode);
            if (treelevel > 2)
            {
                tvResults.SelectedNode = treeNode.Parent;
            }
            else
            {
                tvResults.SelectedNode = treeNode;
            }
        }
    }

Open in new window

And my second attempt:
    List<TreeNode> treeNodes = new List<TreeNode>();
    List<TreeNode> childNodes = new List<TreeNode>();
    int treelevel = 0;
    string price = "";
    string application = "";
    string lrflag = "";
    string interchangenumber = "";
    foreach (var a in data)
    {
        treelevel = a.treelevel;
        application = a.application;
        lrflag = a.lrflag;
        interchangenumber = a.interchangenumber;
        if (a.price > 0)
        {
            price = string.Concat("PRICE:$", a.price.ToString(), " ");
        }
        if (treelevel == a.treelevel)
            childNodes.Add(new TreeNode(String.Concat("(", treelevel, ")   ", application, lrflag, " ", price, "IC:", interchangenumber)));
        else
        {
            if (childNodes.Count > 0)
            {
                treeNodes.Add(new TreeNode(String.Concat("(", treelevel, ")   ", application, lrflag, " ", price, "IC:", interchangenumber), childNodes.ToArray()));
                childNodes = new List<TreeNode>();
            }
            treelevel = a.treelevel;
        }
    }

    if (childNodes.Count > 0)
    {
        treeNodes.Add(new TreeNode(String.Concat("(", treelevel, ")   ", application, lrflag, " ", price, "IC:", interchangenumber), childNodes.ToArray()));
    }
    tvResults.Nodes.AddRange(treeNodes.ToArray());

Open in new window


Still, it isn't right. can anyone help out here?
LVL 27
Eddie ShipmanAll-around developerAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Eddie ShipmanAll-around developerAuthor Commented:
The data is not JSON, I only posted in JSON to show the data. The data is not in hierarchical format as the JSON shows.
0
Eddie ShipmanAll-around developerAuthor Commented:
This is how a coworker did it into a listbox in VB.Net. Problem is, I need it in a TreeView and the same procedure just doesn't work.
Dim cmdx As OleDbCommand = New OleDbCommand(strx, cn)
Dim drx As OleDbDataReader = cmdx.ExecuteReader
ListBox1.Show()

While drx.Read
    Dim firsttl As String = Space(3)
    Dim strq = ""
    Dim sb As New System.Text.StringBuilder()

    ''''''''''''''''''''''''''''''''''''''''''''''''''

    'If drx("treelevel") = 1 And IsDBNull(drx("interchangenumber")) = True Then
    If drx("treelevel") = 1 Then
        ListBox1.Items.Add(drx("application") & " " & drx("lrflag") & " " & drx("price") & " IC:" & drx("interchangenumber"))
        strq = ""
    Else
        strq = ""
        For i = 1 To drx("treelevel")
            strq = sb.Append(firsttl).ToString()
        Next
        ListBox1.Items.Add(strq & drx("application") & " " & drx("lrflag") & " " & drx("price") & " IC:" & drx("interchangenumber"))
        strq = ""
    End If
    ''''''''''''''''''''''''''''''''''''''''''''''''''
End While

Open in new window

0
Exploring ASP.NET Core: Fundamentals

Learn to build web apps and services, IoT apps, and mobile backends by covering the fundamentals of ASP.NET Core and  exploring the core foundations for app libraries.

Eddie ShipmanAll-around developerAuthor Commented:
I modfied the data to add a parentlevel and this code is getting very close:
The problem with it seems to be the LINQ query. I really don't think I want to do this recursively, either, huh?


private void PopulateTreeView(int parentId, TreeNode parentNode)
{
    int treelevel = 0;
    string application = "";
    string lrflag = "";
    string interchangenumber = "";
    var filteredItems = ret.Where(item =>
                                item.parentlevel == parentId);
    TreeNode childNode;
    foreach (var a in filteredItems.ToList())
    {
        string price = "";
        treelevel = a.treelevel;
        application = a.application;
        lrflag = a.lrflag;
        interchangenumber = a.interchangenumber;
        if (a.price > 0)
        {
            price = string.Concat("PRICE:$", a.price.ToString(), " ");
        }
        if (parentNode == null)
            childNode = tvResults.Nodes.Add(String.Concat(application, lrflag, " ", price, "IC:", interchangenumber));
        else
            childNode = parentNode.Nodes.Add(String.Concat(application, lrflag, " ", price, "IC:", interchangenumber));

        PopulateTreeView(a.treelevel, childNode);
    }
}

Open in new window

0
Eddie ShipmanAll-around developerAuthor Commented:
We're getting close with this one, too but it keeps putting all the 5 levels under EACH 4 level, 4 levels under EACH 3 level and so on...

TreeNode childNode = null;
TreeNode parentNode = null;
int treelevel = 0;
int parentlevel = 0;
string application = "";
string lrflag = "";
string interchangenumber = "";
int oldtreelevel = 0;
foreach (var a in data)
{
    TreeNode t = new TreeNode();
    string price = "";
    treelevel = a.treelevel;
    parentlevel = a.parentlevel;
    application = a.application;
    lrflag = a.lrflag;
    interchangenumber = a.interchangenumber;
    if (a.price > 0)
    {
        price = string.Concat("PRICE:$", a.price.ToString(), " ");
    }
    t.Text = String.Concat(application, lrflag, " ", price, "IC:", interchangenumber);
    if (parentlevel == 0)
    {
        tvResults.Nodes.Add(t);
        parentNode = t;
        oldtreelevel = 0 + treelevel;
    }
    else
    {
        parentNode.Nodes.Add(t);
        if (oldtreelevel == treelevel - 1)
        {
            childNode = t;
            t.Tag = treelevel;
        }
        else
        {
            for (int i = treelevel; i == 0; i--)
            {
                parentNode = tvResults.SelectedNode.PrevNode;
            }
            oldtreelevel = parentNode.Level;
        }
    }
}

Open in new window

0
Eddie ShipmanAll-around developerAuthor Commented:
Got it... Based on this solution: http://csharphelper.com/blog/2014/09/load-a-treeview-from-a-tab-delimited-file-in-c/           
            tvResults.Nodes.Clear();
            Dictionary<int, TreeNode> parents = new Dictionary<int, TreeNode>();
            foreach (var a in data)
            {
                string price = "";
                int level = a.treelevel-1;
                if (a.price > 0)
                {
                    price = string.Concat("PRICE:$", a.price.ToString(), " ");
                }

                if (level == 0)
                    parents[level] = tvResults.Nodes.Add(String.Concat(a.application, a.lrflag, " ", price, "IC:", a.interchangenumber));
                else
                    parents[level] =
                        parents[level - 1].Nodes.Add(String.Concat(a.application, a.lrflag, " ", price, "IC:", a.interchangenumber));
                parents[level].EnsureVisible();
            }

            if (tvResults.Nodes.Count > 0) tvResults.Nodes[0].EnsureVisible();

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Eddie ShipmanAll-around developerAuthor Commented:
Based on this colution:
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.