Ray
Ray

Reputation: 427

How to reset Treeview to default display after Treeview.Sort?

I was trying to display a treeview's nodes alphabetically and managed to get it done simply by:

treeview1.Sort();  

it does the job of sorting. but then I'd like to have the option to put the treeview back to its original display state (without the alphabetic sorting).

on another question I saw that I might be able to use the treeview's property: .sorted and set it to true or false but it didn't do anything for me.

I have the data in the control, it's already set in design time.

what is the best way to do this?

Many Thanks in advance!

Upvotes: 0

Views: 2112

Answers (1)

TaW
TaW

Reputation: 54433

Of course getting the content from an outside source would be the most flexible way to fill the Tree, but..

..as the content of the tree has been added in the designer then if there is a lot of data involved the best route may be to salvage these data by moving the designer code into a magical Unsort-function you can call anytime.

Have a good look at the form's Designer.cs file! Here you can find two sections that deal with the loading of the TreeView:

  • The first sit inside the 'forbidden' part: InitializeComponent()with the dire warning that you shouldn't change anything in there. Well, don't worry all we do is copy a few lines from it to the unsort function..

What we need are all lines that declare and create the nodes. They look like this:

System.Windows.Forms.TreeNode treeNode1 = new System.Windows.Forms.TreeNode("John");

Now scroll down to the section the starts with

   // 
   // treeView1
   // 

We don't care about the first few lines that assign a Name and a Location to the TreeView. But we want all the following lines that set the Names and the Texts of all the Nodes; and also all lines the add the root nodes to the TreeView..

We copy all this into a function that starts by clearing the Nodes and resetting the Sorted property. Then come all the lines we have salvaged from the Designer.

The result could look like this:

void unsortTree()
{
   this.treeView1.Nodes.Clear();
   this.treeView1.Sorted = false;
    
   System.Windows.Forms.TreeNode treeNode1 = new System.Windows.Forms.TreeNode("John");
   System.Windows.Forms.TreeNode treeNode2 = new System.Windows.Forms.TreeNode("Paul");
   System.Windows.Forms.TreeNode treeNode3 = new System.Windows.Forms.TreeNode("George");
   System.Windows.Forms.TreeNode treeNode4 = new System.Windows.Forms.TreeNode("Ringo");
   System.Windows.Forms.TreeNode treeNode5 = new System.Windows.Forms.TreeNode("Beatles",
                 new System.Windows.Forms.TreeNode[] 
                 {treeNode1,  treeNode2, treeNode3, treeNode4});
   System.Windows.Forms.TreeNode treeNode6 = new System.Windows.Forms.TreeNode("Byrds");
   System.Windows.Forms.TreeNode treeNode7 = 
         new System.Windows.Forms.TreeNode("Bee Gees");

   // 
   // treeView1
   // 

   treeNode1.Name = "Knoten2";        treeNode1.Text = "John";
   treeNode2.Name = "Knoten3";        treeNode2.Text = "Paul";
   treeNode3.Name = "Knoten4";        treeNode3.Text = "George";
   treeNode4.Name = "Knoten6";        treeNode4.Text = "Ringo";
   treeNode5.Name = "Knoten0";        treeNode5.Text = "Beatles";
   treeNode6.Name = "Knoten1";        treeNode6.Text = "Byrds";
   treeNode7.Name = "Knoten7";        treeNode7.Text = "Bee Gees";

   this.treeView1.Nodes.AddRange(new System.Windows.Forms.TreeNode[]
                                { treeNode5,   treeNode6, treeNode7});

}

We you have tested that this works fine you can delete the nodes from the tree in the designer and add a call to the function to the form load. Do not keep the data in two places!!

Note: As this recreates the Tree content from scratch all user input is lost. If the user can check CheckBoxes or edit Labels you should consider writing a treesave and a treeload function! (Not necessarily targeting a file, maybe just an invisible helper-treeview..)

Note 2:

Since the TreeView indeed does contain CheckBoxes (but neither adds nor deletes Nodes nor changes Texts) we should store and restore the CheckStates.

Adding a Dictionary at class level and these two recursive helper functions is almost all we need:

Dictionary<string, bool> tvCheckStates = null;

void storeChecks(TreeNode node)
{
    if (tvCheckStates.Keys.Contains(node.Name))
        throw new Exception("duplicate node name:" + node.Name);
    else tvCheckStates.Add(node.Name, node.Checked);

    foreach (TreeNode n in node.Nodes) storeChecks(n);
}

void restoreChecks(TreeNode node)
{
    if (tvCheckStates.Keys.Contains(node.Name))
        node.Checked = tvCheckStates[node.Name];
    else throw new Exception("node not found:" + node.Name);

    foreach (TreeNode n in node.Nodes) restoreChecks(n);
}

Finally we call them at the very start and end of the 'unsort':

  {
      if (tvCheckStates == null && treeView1.Nodes.Count > 0) 
          tvCheckStates = new Dictionary<string, bool>();
      else if (treeView1.Nodes.Count > 0) tvCheckStates.Clear();
      foreach (TreeNode node in treeView1.Nodes) storeChecks(node);
      //..

      //..
      if (tvCheckStates != null && treeView1.Nodes.Count > 0) 
          foreach (TreeNode node in treeView1.Nodes) restoreChecks(node);
  }

Note that the Node Names must be unique (as they should).

To persist the states across program runs it should be enough to save the names of the checked nodes..

enter image description here

Upvotes: 1

Related Questions