• 0

C# and making a TreeView out of arrays


Question

So I have encountered a probleem while trying to populate a TreeView control with nodes. I hope that there are a some kind people who t?ke the time and help me figuure out a correct solution.

So lets say I have 3 arrays:

 

["Example", "2", "1"]

{"Example", "2", "2"]

["Example", "3", "0"]

 

I know that my arrays have always exactly 3 elements in them, so the treeview will never have more than 3 childnodes

 

But all I am able to get is

 

Example

 2

  1

Example

 2

  2

Example

 3

  0

 

But the goal would be:

 

Example

 2

  1

  2

 3

  0

 

So where would I start chasing down the answer to my probleem?
Big thanks in advance :)

 

 

Recommended Posts

  • 0


void InitTreeView(List<string[]> arrays) {

            foreach (var array in arrays) {

                AddArray(array, 0, m_treeView.Nodes);

            }

        }

        /// <summary>

        /// Recursively adds each element of the array to the tree

        /// </summary>

        void AddArray(string[] array, int index, TreeNodeCollection nodes) {

            // Termination condition: we've past the bounds of the array

            if (index < array.Length) {

                var nextNode = AddValue(array[index], nodes);

                AddArray(array, index + 1, nextNode.Nodes);

            }

        }

        /// <summary>

        /// If the value exists, returns it, otherwise creates a new value

        /// </summary>

        TreeNode AddValue(string value, TreeNodeCollection nodes) {

            var index = nodes.IndexOfKey(value);

            if (index == -1) {

                var newNode = new TreeNode(value) { Name = value };

                nodes.Add(newNode);

                return newNode;

            }

            return nodes[index];

        }

  • 0

        private static TreeView GetTree(TreeView Tree, List<string[]> Items)
        {
            foreach (string[] item in Items)
            {
                TreeNode parent = new TreeNode();
                parent.Text = item[0];
                TreeNode child = new TreeNode();
                child.Text = item[1];
                TreeNode child2 = new TreeNode();
                child2.Text = item[2];
                child.Nodes.Add(child2);
                parent.Nodes.Add(child);
                Tree.Nodes.Add(parent);
            }
            return Tree;
        }

Well, I have a code  that goes through each array and creates parentnode with array first item, childnode with second and childnode of childnode with third. So thats pretty basic approach

 

  • 0

I imagine you want to do something like the following pseudo code.
Idea is that you create the array of children you want before you create the treenode with the label.

tv = new TreeView();
dict = new Dictionary<String, List<String>>();
arrs = array of those arrays;

for arr in arrs:
     dict[arr[1]].Add(arr[2]);

for (key, value) in dict:
    tv.Nodes.Add(new TreeNode(key, value.ToArray()))
  • 0
  On 22/12/2013 at 14:17, Lant said:

 

I imagine you want to do something like the following pseudo code.

Idea is that you create the array of children you want before you create the treenode with the label.

 

 

Got lost trying to implement something like that, although the approach is right, I need to create the last level nodes first

  • 0

What sort of performance are you looking for?  If you're just talking a few hundred items, then try this approach.

 

Each node should be identifiable via a predictable, unique key of your creation (it could be, literally, the value you're trying to insert).  Try to find your parent node by looking for the key it should have.  If you can't find it, create a new node and insert it.  If it returns something instead, then use that as the parent of the key you're trying to insert.

  • 0
  On 22/12/2013 at 16:55, jakem1 said:

Try a recursive function.

This is the right way to go, I know that, but I am totally unsure how the code should look like.

Regarding to performance, it is important in my case since we're talking about thousands of nodes here.

  • 0
  On 22/12/2013 at 17:01, ka-la said:

This is the right way to go, I know that, but I am totally unsure how the code should look like.

Regarding to performance, it is important in my case since we're talking about thousands of nodes here.

 

As a general rule of thumb, if you find yourself pushing program state into some sort of explicit stack when using an iterative solution (pushing state to a queue for example): you are may just be doing an explicit recursion (what I mean by this is that you are doing the same work that a recursion would do for you) and are may be better suited to just use a recursive solution.

  • 0

This should be very straightforward to convert to C#, but here's the general idea for a recursive solution:

InitTreeView:
    var data = new List<string[]> { " Your data here " };
    foreach array in data:
        AddArray(array, 0, root collection)

AddArray(array, index, nodes):
    // Termination condition: index is past the end of the array
    // Otherwise:
    nextNode = AddValue(array[index], nodes)
    AddArray(array, index + 1, nextNode collection)

AddValue(value, nodes):
    // If node exists in the collection, return it
    // Otherwise create new node with the value, add it and return it
  • 0
  On 26/12/2013 at 17:08, Andre S. said:

 

This should be very straightforward to convert to C#, but here's the general idea for a recursive solution:


InitTreeView:
    var data = new List<string[]> { " Your data here " };
    foreach array in data:
        AddArray(array, 0, root collection)

AddArray(array, index, nodes):
    // Termination condition: index is past the end of the array
    // Otherwise:
    nextNode = AddValue(array[index], nodes)
    AddArray(array[index], index + 1, nextNode collection)

AddValue(value, nodes):
    // If node exists in the collection, return it
    // Otherwise create new node with the value, add it and return it

Some parts of the code still remain as a puzzle for me:

1)  What should AddValue return, a collection or a treenode?

2) AddArray( array[index].... seems weird to me, it expects an array, but your code sends it a value from array with that index

3) What should AddArray return? my best guess so far is, it is just a void and does not return anything.

4) nextNode collection should be nextNode.Nodes ? (case the AddValue returns a treenode)

  • 0
  On 27/12/2013 at 15:08, ka-la said:

Some parts of the code still remain as a puzzle for me:

1)  What should AddValue return, a collection or a treenode?

2) AddArray( array[index].... seems weird to me, it expects an array, but your code sends it a value from array with that index

3) What should AddArray return? my best guess so far is, it is just a void and does not return anything.

4) nextNode collection should be nextNode.Nodes ? (case the AddValue returns a treenode)

1) As I wrote it, it returns a TreeNode. You could just return the collection as well as that's the only thing AddArray needs.

2) Oops that was a mistake, fixed. Should pass array.

3) AddArray is void.

4) Yup.

 

Is this homework?

  • 0
        private static TreeView GetTree(TreeView Tree)
        {
            Tree.BeginUpdate();
            List<string[]> l_tree = new List<string[]>();
            string[] str1 = new string[] {"Example", "2", "1"};
            string[] str2 = new string[] { "Example", "2", "2"};
            string[] str3 = new string[] { "Example", "3", "0" };
            l_tree.Add(str1);
            l_tree.Add(str2);
            l_tree.Add(str3);

            foreach (string[] array in l_tree)
            {
                AddArray(array, 0, Tree.Nodes);
            }
            Tree.EndUpdate();
            return Tree;
        }

        private static void AddArray(string[] array, int index, TreeNodeCollection nodes)
        {
            if (index < 3)
            {
                var nextNode = AddValue(array[index], nodes);
                AddArray(array, index + 1, nextNode.Nodes);
            }
        }

        private static TreeNode AddValue(string value, TreeNodeCollection nodes)
        {
            if (nodes.Count == 0)
            {
                TreeNode newnode = new TreeNode();
                newnode.Text = value;
                nodes.Add(newnode);
                return newnode;
            }
            else
            {
                foreach (TreeNode node in nodes)
                {
                    if (node.Text == value)
                    {
                        return node;
                    }
                    else
                    {
                        TreeNode newnode = new TreeNode();
                        newnode.Text = value;
                        node.Nodes.Add(newnode);
                        return node;
                    }
                }
            }
            return null;
        }

If the initial tree is empty, I get nullreferenceexception, since I cant go through the empty collection in addvalue

Example

 2

  1

    2

    0

  3

 

 

  • 0
  On 27/12/2013 at 22:59, ka-la said:

Sir I am truly thankful for your help, not sure how to return the regards :)

Glad to be of help. :) By the way, you can write this:

    List<string[]> l_tree = new List<string[]>();
    string[] str1 = new string[] {"Example", "2", "1"};
    string[] str2 = new string[] { "Example", "2", "2"};
    string[] str3 = new string[] { "Example", "3", "0" };
    l_tree.Add(str1);
    l_tree.Add(str2);
    l_tree.Add(str3);

more simply as:

    var l_tree = new List<string[]> {
        new[] { "Example", "2", "1" },
        new[] { "Example", "2", "2" },
        new[] { "Example", "3", "0" }
    }
  • 0

I haven't tested but are you required to use the new[] syntax for the string arrays(i.e. string[]) in this example or can you get away with removing that part because of the string type?

  • 0
  On 28/12/2013 at 02:56, snaphat (Myles Landwehr) said:

I haven't tested but are you required to use the new[] syntax for the string arrays(i.e. string[]) in this example or can you get away with removing that part because of the string type?

new[] { "a", "b" }

 is shorthand (since C# 3.0) for :

new string[] { "a", "b" }

There's also a special case (which was just to copy C/C++ in C# 1.0) for assignment to a new variable, where you can omit everything:

string[] array = { "a", "b" }

But then you have to explicitely type the variable, you can't use var. IMO this is old fashioned and for consistency everyone should write:

var array = new[] { "a", "b" }

Of course this works for all types and not just string.

  • 0
  On 28/12/2013 at 03:12, Andre S. said:
new[] { "a", "b" }

 is shorthand (since C# 3.0) for :

new string[] { "a", "b" }

There's also a special case (which was just to copy C/C++ in C# 1.0) for assignment to a new variable, where you can omit everything:

string[] array = { "a", "b" }

But then you have to explicitely type the variable, you can't use var. IMO this is old fashioned and for consistency everyone should write:

var array = new[] { "a", "b" }

Of course this works for all types and not just string.

 

 

Right, right, Is the special case for assignment still possible in newer C# revisions or is is not-recommended/depreciated? I initially thought that you were being a bit more verbose with the new[] statement in the compound list assignment because it was required. Sounds like you were doing it more for consistencies sake; which is fair.

  • 0
  On 28/12/2013 at 03:28, snaphat (Myles Landwehr) said:

Right, right, Is the special case for assignment still possible in newer C# revisions or is is not-recommended/depreciated? I initially thought that you were being a bit more verbose with the new[] statement in the compound list assignment because it was required. Sounds like you were doing it more for consistencies sake; which is fair.

I'm doing it in the list assignment because it is and has always been required in that case. You can omit new[] only if you assign the array expression to an explicitely typed variable. This, in addition to the fact that this syntax contradicts the usual C# principle that every expression has a type, makes it inconsistent and confusing in my eyes, but it's still supported. It's only my opinion and not any sort of official deprecation or recommendation.

  • Like 1
  • 0
  On 28/12/2013 at 03:56, Andre S. said:

I'm doing it in the list assignment because it is and has always been required in that case. You can omit new[] only if you assign the array expression to an explicitely typed variable. This, in addition to the fact that this syntax contradicts the usual C# principle that every expression has a type, makes it inconsistent and confusing in my eyes, but it's still supported. It's only my opinion and not any sort of official deprecation or recommendation.

 

Fair enough, I'll say that the bolded text is a good reason to use it in the above code regardless of opinion ;-)

  • 0
  On 28/12/2013 at 04:09, snaphat (Myles Landwehr) said:

Fair enough, I'll say that the bolded text is a good reason to use it in the above code regardless of opinion ;-)

I'm not sure if we're talking past each other... this:

new List<string[]> {
     { "a", "b", "c" },
     { "b", "c", "d" }
}

is not and never was legal C#.

This topic is now closed to further replies.
  • Posts

    • Staged. It's a requirement that vehicles are strapped down to the bed. Usually wheel and/or chassis tie downs are used. That appears to just be on the winch.
    • I feel Apple's big problem is the lack of big data to train any AI LLM model. They have statistics on usage, but they don't have the written social media, messaging (they were early adopters of end-to-end encryption), they didn't scrape the Internet before the book companies and new sources were wise. So they have no choice but to use a third party LLM provider. Which ties them in knots with their own stance on security and privacy. In short, they are royally stuffed when it comes to developing an in-house AI.
    • Nothing is black and white. Democracy can suck, just as communism can. The risk is people who blindly think one is vastly superior over the other. Democracy needs a lot to make it work well, and there are many examples around the world of it. Good education, mandatory voting, accessible voting, and removing money from politics are just a few elements that need to be sorted for a functional democracy. The USA is the playbook on what not to do with democracy.
    • Weekend PC Game Deals: Showcase specials, Timeloop freebies, Resident Evils, and more by Pulasthi Ariyasinghe Weekend PC Game Deals is where the hottest gaming deals from all over the internet are gathered into one place every week for your consumption. So kick back, relax, and hold on to your wallets. The Epic Games Store brought the finale of its Mega Sale mystery giveaways this week, and that involved giving away the Bethesda and Arkane title Deathloop alongside the indie title Ogu and the Secret Forest. Deathloop comes in as a time-loop FPS adventure that puts you into the shoes of an assassin that must take down eight targets in a single day to escape the time travel shenanigans. In usual Arkane fashion, each target can be taken care of in multiple ways, and there are supernatural powers that give the player upgrades like teleportation and telekinesis. There is an invasion mechanic for taking down other players in their campaigns too. As for Ogu and the Secret Forest, it's an indie adventure featuring hand-drawn characters and intricate puzzles. The 2D game involves befriending characters across a fantasy land as baby Ogu, with plenty of exploration elements and boss battles available. The Deathloop and Ogu and the Secret Forest giveaways are available on the Epic Games Store until June 12. On the same day, the store will begin a giveaway for the humorous hospital simulation entry Two Point Hospital. Next, we look at a giveaway happening on the Steam store. Gearbox is only a few months away from releasing Borderlands 4, and to prepare some new fans, Borderlands 2 is free to claim on Steam right now. The four-player cooperative title offers a humorous campaign filled with wacky villains, a massive amount of weapons to loot, and skill trees that let you break the balance entirely. The Borderlands 2 giveaway on Steam is live right now. It's slated to come to an end on June 8 at 10am PT. Since it's a new month, the Humble Choice bundle went through its standard refresh earlier this week, releasing eight more games for subscription holders to add to their library. This time, you can grab Warhammer 40K: Boltgun, Legacy of Kain Soul Reaver 1 and 2 Remastered, Nobody Wants to Die, Dungeons of Hinterberg, Tchia, Sker Ritual, Biped, and Havendock. It will cost you $12 to get all eight games. As a month-long Humble Choice Bundle, though, you can ponder the contents until July 1, when a new selection of games will replace these ones. In the regular bundle space, the Humble Store is also celebrating showcase season with its IGN Live bundle. This carries Slay the Spire, Potion Craft: Alchemist Simulator, and Bloodroots in the starting tier for $10. Next, paying $16 gets you copies of Art of Rally, Old World, and Black Book. Lastly, paying the full $22 for the bundle will add on copies of The Medium and Wartales. The bundle has a two-week counter attached to it, so you have plenty of time to decide on it. Big Deals Alongside plenty of showcase-related sales, massive franchise discounts from 2K, Capcom, Techland, and more are currently available for you to check out. Here are our hand-picked big deals for this weekend: Lies of P – $29.99 on Steam Company of Heroes 3 – $29.99 on Steam Sekiro: Shadows Die Twice - GOTY Edition – $29.99 on Steam Dragon's Dogma 2 – $29.39 on Steam Satisfactory – $27.99 on Steam Diablo IV – $27.49 on Steam Another Crab's Treasure – $20.99 on Steam Resident Evil 4 – $19.99 on Steam Tetris Effect: Connected – $19.99 on Steam Dying Light 2 Stay Human: Reloaded Edition – $19.79 on Steam No Man's Sky – $19.62 on Gamebillet Chained Echoes – $18.74 on Steam Starship Troopers: Terran Command – $17.99 on Steam The Outlast Trials – $15.99 on Steam Tales from the Borderlands – $14.99 on Steam Phasmophobia – $14.99 on Steam Divinity: Original Sin 2 - Definitive Edition – $13.49 on Steam Gotham Knights – $11.99 on Steam Receiver 2 – $9.99 on Steam Resident Evil Village – $9.99 on Steam Goat Simulator 3 – $9.89 on Steam Borderlands Game of the Year Enhanced – $9.89 on Steam The Outer Worlds – $9.89 on Steam Dorfromantik – $9.79 on Steam Turnip Boy Robs a Bank – $9.74 on Steam Ni no Kuni II: Revenant Kingdom – $9.59 on Steam Batman: Arkham Collection – $8.99 on Steam Escape Academy – $8.00 on Steam Resident Evil 7 Biohazard – $7.99 on Steam Inscryption – $7.99 on Steam Devil May Cry 5 – $7.49 on Steam Watch_Dogs 2 – $7.49 on Steam Suicide Squad: Kill the Justice League – $6.99 on Steam Control Ultimate Edition – $5.99 on Steam Injustice 2 Legendary Edition – $5.99 on Steam Manifold Garden – $4.99 on Steam Cultist Simulator – $4.99 on Steam Watch_Dogs – $4.99 on Steam Dragon's Dogma: Dark Arisen – $4.79 on Steam ARK: Survival Evolved – $4.49 on Steam Batman: Arkham Origins – $3.99 on Steam Dying Light – $3.99 on Steam PAYDAY 2 – $3.29 on Steam WRC 9 FIA World Rally Championship – $2.99 on Steam Alan Wake – $2.99 on Steam Borderlands 3 – $2.99 on Steam Among Us – $2.99 on Steam Hitman: Absolution – $1.99 on Steam Borderlands 2 – $0 on Steam Ogu and the Secret Forest – $0 on Epic Store Deathloop – $0 on Epic Store DRM-free Specials The GOG store's latest DRM-free specials for this weekend are touting Atari classics, story-rich games, and much more. Here are some highlights: Atari 50: The Anniversary Celebration - $19.99 on GOG The Thaumaturge - $19.24 on GOG Turok 3: Shadow of Oblivion Remastered - $17.99 on GOG STAR WARS: Dark Forces Remaster - $16.49 on GOG INDIKA - $16.24 on GOG Blood West - $12.49 on GOG Shadowrun Trilogy - $10.07 on GOG Disco Elysium - The Final Cut - $9.99 on GOG Pathologic 2 - $6.99 on GOG Tacoma - $6.59 on GOG Little Nightmares - $4.99 on GOG RollerCoaster Tycoon 3: Complete Edition - $4.99 on GOG Gone Home - $4.94 on GOG Blade Runner - Enhanced Edition - $2.49 on GOG Blood: Fresh Supply - $2.49 on GOG SiN Gold - $1.99 on GOG The Wheel of Time - $1.49 on GOG RollerCoaster Tycoon Deluxe - $1.19 on GOG Pirates! Gold Plus - $1.19 on GOG Sid Meier's Colonization - $1.19 on GOG POSTAL 2 - $0.99 on GOG Keep in mind that availability and pricing for some deals could vary depending on the region. That's it for our pick of this weekend's PC game deals, and hopefully, some of you have enough self-restraint not to keep adding to your ever-growing backlogs. As always, there are an enormous number of other deals ready and waiting all over the interwebs, as well as on services you may already subscribe to if you comb through them, so keep your eyes open for those, and have a great weekend.
  • Recent Achievements

    • First Post
      Mr bot earned a badge
      First Post
    • First Post
      Bkl211 earned a badge
      First Post
    • One Year In
      Mido gaber earned a badge
      One Year In
    • One Year In
      Vladimir Migunov earned a badge
      One Year In
    • Week One Done
      daelos earned a badge
      Week One Done
  • Popular Contributors

    1. 1
      +primortal
      492
    2. 2
      snowy owl
      255
    3. 3
      +FloatingFatMan
      252
    4. 4
      ATLien_0
      224
    5. 5
      +Edouard
      187
  • Tell a friend

    Love Neowin? Tell a friend!