Link to home
Start Free TrialLog in
Avatar of Eddie Shipman
Eddie ShipmanFlag for United States of America

asked on

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?
Avatar of Misha
Misha
Flag of Russian Federation image

Avatar of Eddie Shipman

ASKER

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.
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

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

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

ASKER CERTIFIED SOLUTION
Avatar of Eddie Shipman
Eddie Shipman
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Based on this colution: