Sorting Treenodes in treeview |
|
Author |
Message |
Greg Knierim
|
Posted: Windows Forms General, Sorting Treenodes in treeview |
Top |
I am trying to figure out how to sort the treenodes in a treeview. I am allowing the user to add and update the nodes and their text at runtime. Therefore, I need to implement the Sort procedure in the AfterLabelEdit event. However, there are a few problems I'm not sure how to address. Has anyone done this I can't seem to find a good answer.
My treeview is only 1 level deep. A parent node can only have child nodes and those child nodes cannot have any child nodes. When I add a child node, it adds it at the bottom initially with some default text 'New item' and goes into Edit mode. After I am done editing the text, the AfterLabelEdit event is fired and thats where I save the node to the database and where I would ideally like to resort ONLY that parents nodes that I just added. I don't see a need to resort the whole treeview when I only want to sort the current parent and those nodes.
Does anyone have any thoughts on how to implement this The problem is that the new node Text value is still set to 'New Item' in the AfterLabelEdit event and therefore if I sort it, I will need to use the new value entered, e.Label and not e.Text.
Thoughts or comments
Windows Forms16
|
|
|
|
|
n0n4m3
|
Posted: Windows Forms General, Sorting Treenodes in treeview |
Top |
|
|
|
Greg Knierim
|
Posted: Windows Forms General, Sorting Treenodes in treeview |
Top |
I have actually been trying that and now I remember what my problem was. (Its been a couple of months since I looked at this.)
My problem is that the NodeSorter class works fine if I call it from a button click after I have added the new node. If I try to call it in the AfterLabelEdit event, it sorts the default text of the new node ('New Folder') and makes the last node the text that I entered, overwriting the last node text.
Is there another event that fires after the AfterLabelEdit event that I could use to trigger the NodeSorter automatically when adding new nodes
Thanks, Greg
|
|
|
|
|
NateV
|
Posted: Windows Forms General, Sorting Treenodes in treeview |
Top |
Hi there,
Here's something I knocked together....It's not good or fancy like a NodeSorter but it seems to work OK if you put it in the AfterLabelEdit event.
Just one thing, it seems to result in the unusual behaviour of retaining the focus/editability on the node whose editing fired the AfterLabelEdit event. I don't think it's a big deal but it could be annoying....Haven't figured out a workaround yet but might update this post when I do.
Private Sub TreeView1_AfterLabelEdit(ByVal sender As System.Object, ByVal e As System.Windows.Forms.NodeLabelEditEventArgs) Handles TreeView1.AfterLabelEdit Dim theParentNode As TreeNode = e.Node.Parent Dim indexInCollection As Integer = e.Node.Index Dim newPos As Integer = 0 Dim sortedNodes As List(Of String) = New List(Of String) Dim newLabelText As String = e.Label
'We do not need to fire if nothing has changed (e.Label = e.Node.Text) 'We do not want infinite firing (IsNothing(e.Label)) If e.Label = e.Node.Text Or IsNothing(e.Label) Then Exit Sub End If
If IsNothing(theParentNode) Then 'Top level node For Each node As TreeNode In TreeView1.Nodes If node.Index = indexInCollection Then sortedNodes.Add(newLabelText) Else sortedNodes.Add(node.Text) End If Next sortedNodes.Sort()
newPos = sortedNodes.IndexOf(newLabelText) TreeView1.Nodes.Remove(e.Node) TreeView1.Nodes.Insert(newPos, e.Node) Else '1st level node For Each node As TreeNode In theParentNode.Nodes If node.Index = indexInCollection Then sortedNodes.Add(newLabelText) Else sortedNodes.Add(node.Text) End If Next sortedNodes.Sort()
newPos = sortedNodes.IndexOf(newLabelText) theParentNode.Nodes.Remove(e.Node) theParentNode.Nodes.Insert(newPos, e.Node) End If End Sub
Hope that helps a bit, but sorry if it doesn't
|
|
|
|
|
Greg Knierim
|
Posted: Windows Forms General, Sorting Treenodes in treeview |
Top |
Yea, I saw a post very similar to that but didn't like the idea of removing and adding the nodes back but I believe it would work. I may end up trying it if I can't deal with the resort manual button.
What I need is another event like LabelEditedComplete or something that fires after the AfterLabelEdit event so that the sort can take place. Oh well...
Thanks for the help!
Greg
|
|
|
|
|
Peter Huang - MSFT
|
Posted: Windows Forms General, Sorting Treenodes in treeview |
Top |
Hi Greg,
I think another way was to use a timer. We can enable the timer after the added the node. And after you sort the treeview, stop the timer.
If you still have any concern, please feel free to post here.
Best regards, Peter Huang
|
|
|
|
|
Greg Knierim
|
Posted: Windows Forms General, Sorting Treenodes in treeview |
Top |
Now that's an interesting approach/hack. I will give it a try and let you know how it works.
Thanks, Greg
|
|
|
|
|
Greg Knierim
|
Posted: Windows Forms General, Sorting Treenodes in treeview |
Top |
I have this working now where it automatically resorts after adding a node. Here is how.
I initially used a System.Timers.Timer object however, I soon found out that if you start the Timer in the AfterLabelEdit event, and then try to do something in the Timer_Tick event, you will get an exception stating that you cannot make cross-thread calls this way. So...plan B.
I used the BackgroundWorker component. This is the preferred way to implement multithreading. The Worker thread runs your DoWork event and then runs the RunWorkerCompleted event. So, here is my solution:
In the AfterLabelEdit event, after I added my node and saved it to the database, I called mybgWorker.RunWorkerAsync() after all my event processing was done. I then added the following bgWorker events:
Private Sub bgWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) Handles bgWorker.RunWorkerCompleted tvMain.TreeViewNodeSorter = New NodeSorter() End Sub
Private Sub bgWorker_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles bgWorker.DoWork Thread.Sleep(100) End Sub
And thats it. There is a little flicker when the tree resorts but so far it looks like this will work.
Thoughts or questions
Greg
|
|
|
|
|
jlandheer
|
Posted: Windows Forms General, Sorting Treenodes in treeview |
Top |
Hi Greg
I also used this approach. I got a few tips for you:
- In stead of creating a new NodeSorter() you can simply call the Sort() method (assign the NodeSorter after the InitializeComponent() call)
- Put a Treeview.BeginUpdate() before, and a Treeview.EndUpdate() after calling Treeview.Sort() to prevent flicker and let sorting work faster because the treeview isn't updated when sorting.
- Is is best to check whether the background worker is busy, before calling RunWorkerAsync(). You can do this by defining a private boolean for a resort after the worker has completed. (A 10th of a second gives this a very small chance, though you never know for sure...)
Hope this helps.
Best regards,
Jeroen Landheer.
|
|
|
|
|
Greg Knierim
|
Posted: Windows Forms General, Sorting Treenodes in treeview |
Top |
Thanks, the BeginUpdate and EndUpdate took care of the flicker problem.
Greg
|
|
|
|
|
|
|