Load a TreeView from a tab-delimited file in C#

example

This example shows how to Load a TreeView from a tab-delimited file. When it starts, the program loads the following text file into its TreeView control.

Food
        Vegetables
                Beans
                Peas
                Lettuce
        Desserts
                Ice Cream
                Cookies
                        Peanut Butter Chip
                        Chocolate Chip
                Cake
        Fruit
                Bananas
                Peaches
Sports
        Volleyball
        Baseball

The following code shows how the program loads its TreeView control.

// Load a TreeView control from a file that uses tabs
// to show indentation.
private void LoadTreeViewFromFile(string file_name, TreeView trv)
{
    // Get the file's contents.
    string file_contents = File.ReadAllText(file_name);

    // Break the file into lines.
    string[] lines = file_contents.Split(
        new char[] {'\r', '\n'},
        StringSplitOptions.RemoveEmptyEntries);

    // Process the lines.
    trv.Nodes.Clear();
    Dictionary parents =
        new Dictionary();
    foreach (string text_line in lines)
    {
        // See how many tabs are at the start of the line.
        int level = text_line.Length -
            text_line.TrimStart('\t').Length;

        // Add the new node.
        if (level == 0)
            parents[level] = trv.Nodes.Add(text_line.Trim());
        else
            parents[level] =
                parents[level - 1].Nodes.Add(text_line.Trim());
        parents[level].EnsureVisible();
    }

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

First the program uses System.IO.File.ReadAllText to read the text file into a string. It then splits the file into lines using \r and \n characters as delimiters. It removes any blank lines, which may represent actual blank lines or may be due to the file containing \r\n combinations. (This is why the program doesn’t just use ReadAllLines. The Split method lets is easily remove blank lines but ReadAllLines doesn’t.)

Next the code clears the TreeView control and creates the parents dictionary to hold the most recent node at each level of the tree. For example, parents[2] will hold the most recently added node at level 2 in the tree. Later, if the program needs to add a node at level 3 of the tree, it can use parents[2] as its parent. Initially parents is empty.

The then code loops over the lines in the file. For each line, it counts the number of tab characters are at the beginning of the line to determine the node’s level in the tree. It does that by using Trim to remove leading tab characters and then subtracting the string’s new length from its original length.

Now the code creates a new node for the line. If the node is at level 0, the program adds it to the TreeView‘s Nodes collection to make it a top-level node. If the node is not at level 0, the code adds it as a child of the previously saved node at level - 1 in the tree, which was recorded in parents[level - 1]. In either case, the code saves the new node in parents[level] in case the program needs to add a node as a child of this one.

After adding the node, the program calls the node’s EnsureVisible method to make sure its parent is expanded.

After adding all of the nodes, the code ensures the first node is visible so the TreeView displays its top node if it is too long to show all of the nodes at the same time.


Download Example   Follow me on Twitter   RSS feed




This entry was posted in controls, files and tagged , , , , , , , , . Bookmark the permalink.

11 Responses to Load a TreeView from a tab-delimited file in C#

  1. Chris says:

    Hi Rod,

    I’m trying to use your above code but I keep getting a compile error:
    “Using the generic type ‘System.Collections.Generic.Dictionary’ requires 2 type arguments”

    I get that for the line:
    Dictionary parents = new Dictionary();

    Do you have any suggestions?

    • RodStephens says:

      Sorry. When the web site was converted to WordPress, it mangled a lot of code that includes brackets. That statement should be:

      Dictionary<int, TreeNode> parents =
          new Dictionary<int, TreeNode>();

      If you download the example program (for any of the site's examples), you can see the correct code without any web mangling.

  2. Barry says:

    Thanks Rod for posting your simple, elegant solution.** I’ve incorporated it into the GTK# (Linux) “outliner” app that I’m developing and I credited you for the logic. Nice going!
    ___

    ** You only need to retain as many past parents as there are levels in the tree and at any given level, a new node’s parent is always the most recent one saved. I was gonna use a stack until I saw your post. Thanks for saving me the brain twister — I’m getting too old for this shit. 😉

  3. this article save my life, i am undergraduate thesis now.
    i still can’t believe my parsing string algorithm works perfectly, i can create the parse tree representation under treeview control using this example.

    thanks for sharing, dear Rod Stephen.

  4. Joe says:

    Great, very helpful article. Thanks!

  5. Dam Swain says:

    Hi Rod,
    I have a similar requirement. Can you please help me on this.
    I have a datatable. In the url field of the datatable i have urls to pages like
    http://infinite.com/Business/LMS/ManagementSystem/Pages/Goals.aspx.
    http://infinite.com/Business/PMS/Achievement/Pages/achieve.aspx.
    Here Business, LMS, ManagementSystem etc are subsites.
    The requirement is data should be displayed in tree structure.

    +Business
    +LMS
    +ManagementSystem
    Goals.aspx Url(Pageurl)
    +PMS
    +Achievement
    achieve.aspx Url(Pageurl)

    • RodStephens says:

      Do you mean you want it like this:

      Business
          LMS
              ManagementSystem
                  Goals.aspx Url(Pageurl)
          PMS
              Achievement
                  achieve.aspx Url(Pageurl)
      • Dam Swain says:

        Hi Rod,
        Thanks for your response. Let me explain in more details. I have following page urls in a data table including all other details for the page like Title, responsible person for the page, last modified date etc. for the page in each rows of data table.
        Now I want to display all the pages based on their position in the site like below image.
        http://infinite.com/Business/LMS/ManagementSystem/Pages/Goals.aspx.
        http://infinite.com/Business/PMS/Achievement/Pages/achieve.aspx.
        http://infinite.com/News/PMS /Pages/Test.aspx.

        Title Responsibility Url Last Modified
        + Business
        + LMS
        + ManagementSystem
        Goals.aspx Page Owner …/ ManagementSystem/Pages/Goals.aspx 12/10/2016
        +PMS
        + Achievement
        achieve.aspx Page Owner Full Page url 05/07/2015
        +News
        Test.aspx Page Owner Full Page url 02/03/2017
        + LMS
        + ManagementSystem

        • Dam Swain says:

          Yes Rod,
          you are almost right. Do not know why alignment is getting changed after posting. It would have been great if i could paste an image.
          Title Responsibility Url Last Modified
          + Business
          + LMS
          + ManagementSystem
          Goals.aspx Page Owner Full Page url 12/10/2016
          +PMS
          + Achievement
          achieve.aspx Page Owner Full Page url 05/07/2015
          +News
          Test.aspx Page Owner Full Page url 02/03/2017
          + LMS
          + ManagementSystem

        • RodStephens says:

          You can include indentation if you surround the text with <pre>…</pre> tags.

          For some reason, your picture URLs don’t work. Can you try again? And maybe try the text with indentation>

          • Dam Swain says:

            Title Responsibility Url Last Modified
            + 1Business
            + 2LMS
            + 3ManagementSystem
            Goals.aspx Page Owner Full Page url 12/10/2016
            +2PMS
            +3 Achievement
            achieve.aspx Page Owner Full Page url 05/07/2015
            +1News
            Test.aspx Page Owner Full Page url 02/03/2017
            + 2LMS
            + 3ManagementSystem

            I am numbering the nodes. i think this will give a clear idea.
            “Title”,”Responsibility”, “Url”, “Last Modified” are the fields to be displayed under nodes.
            I have all these data in a c# datatable and datatable contains all these fields.
            Url field contains the urls fields as shown before.

Leave a Reply

Your email address will not be published. Required fields are marked *