|
Hi, Does anyone know to sort nodes under a particular node in a tree view? I got a treeview with one root and three child nodes e.g. - root - - node1 - - node2 - - node3 - These nodes would have their independent structures/node hierarchies under them. Now, the requirement is to sort only the structures/node hierarchies under these child nodes i.e. node1, node2 and node3; on the click of a button I tried IComparer but somehow I have not been able to make it skip the first three nodes under root Anyone with clues? I am using VB .NET 2005 ~Apploader
|
| Apploader Friday, September 11, 2009 9:21 AM |
This worked, albeit with some hacking: public partial class Form1 : Form { public Form1() { InitializeComponent(); } private class MySorter : System.Collections.IComparer { public int Compare(object x, object y) { TreeNode a = (TreeNode)x; TreeNode b = (TreeNode)y; if (a.Level != b.Level) throw new InvalidOperationException(); // Only sort level 1 nodes alphabetically, rest by their existing index if (a.Level == 1) return String.Compare(a.Text, b.Text); else return (int)a.Tag - (int)b.Tag; } } private void button1_Click(object sender, EventArgs e) { WorkAroundIndexProblem(treeView1.Nodes); treeView1.TreeViewNodeSorter = new MySorter(); treeView1.Sort(); } private void WorkAroundIndexProblem(TreeNodeCollection nodes) { for (int ix = 0; ix < nodes.Count; ++ix) { nodes[ix].Tag = ix; WorkAroundIndexProblem(nodes[ix].Nodes); } }
Hans Passant.- Marked As Answer bynobugzMVP, ModeratorMonday, September 14, 2009 11:02 AM
-
|
| nobugz Friday, September 11, 2009 12:08 PM |
You want to sort the tree hierarchy at first child level which is in your example case[node1,node2,node3] or you want to sort the child hierarchy of node1 or node2 or node2 or all ? Please give an example with some more data and explain it with before sorting and after sorting. |
| AUmidh Friday, September 11, 2009 10:19 AM |
I want to sort nodes after the first child level E.g. Before sort --> Industry - Silicon HJoint Brand2 Brand1 CBranch Expression Expressions1 Expressions8 Expressions2 Rate Rate1 Rate9 Rate2 The root and the first three children (in this case "Silicon", "Expression" and "Rate") would remain where they are. I need to sort nodes which are placed after these Hence, after sort --> Industry - Silicon Brand1 Brand2 CBranch HJoint Expression Expressions1 Expressions2 Expressions8 Rate Rate1 Rate2 Rate9 Hope, this clarifies ~Apploader |
| Apploader Friday, September 11, 2009 11:41 AM |
I will definitely try this, because once i faced such type of problem and i solved that. |
| AUmidh Friday, September 11, 2009 11:48 AM |
This worked, albeit with some hacking: public partial class Form1 : Form { public Form1() { InitializeComponent(); } private class MySorter : System.Collections.IComparer { public int Compare(object x, object y) { TreeNode a = (TreeNode)x; TreeNode b = (TreeNode)y; if (a.Level != b.Level) throw new InvalidOperationException(); // Only sort level 1 nodes alphabetically, rest by their existing index if (a.Level == 1) return String.Compare(a.Text, b.Text); else return (int)a.Tag - (int)b.Tag; } } private void button1_Click(object sender, EventArgs e) { WorkAroundIndexProblem(treeView1.Nodes); treeView1.TreeViewNodeSorter = new MySorter(); treeView1.Sort(); } private void WorkAroundIndexProblem(TreeNodeCollection nodes) { for (int ix = 0; ix < nodes.Count; ++ix) { nodes[ix].Tag = ix; WorkAroundIndexProblem(nodes[ix].Nodes); } }
Hans Passant.- Marked As Answer bynobugzMVP, ModeratorMonday, September 14, 2009 11:02 AM
-
|
| nobugz Friday, September 11, 2009 12:08 PM |
Try This, Its my own effort and i test it. it work as you require private void button1_Click(object sender, EventArgs e) { TreeNode rNode = treeView1.Nodes[0]; if (Equals(rNode, null) == false) { foreach (TreeNode cNode in rNode.Nodes) // First Level Node. { SortNodeItem(cNode); } } } private void SortNodeItem(TreeNode tNode) { for (int pass = 0; pass < tNode.Nodes.Count - 1; pass++) { int potentialSmallest = pass; for (int i = pass + 1; i < tNode.Nodes.Count; i++) { int res = string.Compare(tNode.Nodes[i].Text, tNode.Nodes[potentialSmallest].Text); if (res< 0) { potentialSmallest = i; } } string temp = tNode.Nodes[pass].Text; tNode.Nodes[pass].Text = tNode.Nodes[potentialSmallest].Text; tNode.Nodes[potentialSmallest].Text = temp; } foreach (TreeNode mcNode in tNode.Nodes) { SortNodeItem(mcNode); } } |
| AUmidh Friday, September 11, 2009 1:00 PM |
The above code work if you only want to swap text of the Node because i only swap the text of the node. if you want to sort Nodes of the tree then you have to swap the Nodes. |
| AUmidh Friday, September 11, 2009 1:01 PM |
Thanks for the quick replies. I will try both of these methods and revert back ~Apploader
|
| Apploader Friday, September 11, 2009 1:11 PM |
Ok, But let me inform about the results. |
| AUmidh Friday, September 11, 2009 1:47 PM |
Ok; here goes The swapping of text methods works fine. But, it would be dangerous for me to do it :) I tried swapping nodes directly, however, it simply adds them! Here is the code in VB --> Private Sub SortNodeItem(ByVal tNode As TreeNode) For pass As Integer = 0 To tNode.Nodes.Count - 2 Dim potentialSmallest As Integer = pass Dim i As Integer = pass + 1 For i = pass + 1 To tNode.Nodes.Count - 1 Dim res As Integer = String.Compare(tNode.Nodes(i).Text, tNode.Nodes(potentialSmallest).Text) If (res < 0) Then potentialSmallest = i End If If potentialSmallest = i Then Dim tempNode As TreeNode = tNode.Nodes(pass) tNode.Nodes(pass) = tNode.Nodes(potentialSmallest) tNode.Nodes(potentialSmallest) = tempNode End If Next Next For Each mcNode As TreeNode In tNode.Nodes SortNodeItem(mcNode) Next End Sub Swapping .Text works fine I guess, I would have to try some other method to swap tree nodes @nobugz: I don't want to sort the first children of root nodes ~Apploader
|
| Apploader Friday, September 11, 2009 2:40 PM |
No You don't try another way, Tell Me which properties of a node you are using? As i Guess the most common one are , tag,Text,Name So why you don't swap the properties only like you swap the text. Just do it and get your results. |
| AUmidh Friday, September 11, 2009 2:45 PM |
I use these properties --> 1) Name 2) Text 3) ImageKey 4) SelectedImageKey I cannot do keep on swapping properties since the nodes to be sorted would have children as well. I have to sort nodes themselves Here is the method that I had thought of --> 1) Scan each and every node and prepare a list of fullpaths (individually for all three constant nodes) 2) Sort the list 3) Drop the tree 4) Re-create the tree using the list created in step 1 and sorted in step 2 However, this method is very crude and I was hoping that there are better ways to achieve this ~Apploader
|
| Apploader Friday, September 11, 2009 3:25 PM |
But i think it would not be an efficient way. Try But i still prefer you to swap your four properties as you already test the algo. |
| AUmidh Friday, September 11, 2009 4:23 PM |
@nobugz: I don't want to sort the first children of root nodes
Well, that's simple to change in my code. Just change the Level test from 1 to 2.
Hans Passant. |
| nobugz Friday, September 11, 2009 4:37 PM |
@nobugz: Thanks. My bad for not spotting it. Now, it does work! Here is the code in VB Public Class NodeSorter Implements IComparer ' Compare the length of the strings, or the strings ' themselves, if they are the same length. Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements IComparer.Compare Dim a As TreeNode = CType(x, TreeNode) Dim b As TreeNode = CType(y, TreeNode) If (a.Level <> b.Level) Then Throw New InvalidOperationException() End If 'Only sort level 1 nodes alphabetically, rest by their existing index If (a.Level = 2) Then Return String.Compare(a.Text, b.Text) Else Return CInt(a.Tag - b.Tag) End If End Function End Class Private Sub button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles button1 .Click For Each tempNode As TreeNode In tvHome.Nodes WorkAroundIndexProblem(tvHome.Nodes) Next tvHome.TreeViewNodeSorter = New NodeSorter() tvHome.Sort() End Sub Private Sub WorkAroundIndexProblem(ByVal nodes As TreeNodeCollection) For ix As Integer = 0 To nodes.Count - 1 nodes(ix).Tag = ix WorkAroundIndexProblem(nodes(ix).Nodes) Next End Sub
|
| Apploader Monday, September 14, 2009 7:04 AM |
@nobugz This code seems to sort even when I try to add nodes to the tree. Is there someway to stop this from executing when a user add nodes to a tree? Someway where it would just do the job only when called? |
| Apploader Thursday, September 17, 2009 12:10 PM |
After you call TreeView.Sort(), it stays sorted. You have to explicitly set Sorted = false to stop that.
Hans Passant. |
| nobugz Thursday, September 17, 2009 12:20 PM |