?
Solved

VB2005 + TreeView + TreeViewNodeSorter property

Posted on 2006-05-30
27
Medium Priority
?
2,832 Views
Last Modified: 2012-06-22
Hi

I am giving a try to the new TreeViewNodeSorter property of the Treeview control in VB 2005.

The help files says:
"After the TreeViewNodeSorter is set, if the Sorted property is set to true, the nodes will be sorted in alphabetical order."

But nothing is changed in my treeview when I set Sorted to True after having set the TreeViewNodeSorter to a custom compare class.

How can I revert back to a plain sort?
0
Comment
Question by:Éric Moreau
  • 14
  • 13
27 Comments
 
LVL 70

Author Comment

by:Éric Moreau
ID: 16795214
And I have tried to set the TreeViewNodeSorter property to Nothing before setting Sorted to True and that did not fix the problem!
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 16797701
Eric,

Can you show me the TreeViewNodeSorter implementation, please?

Bob
0
 
LVL 70

Author Comment

by:Éric Moreau
ID: 16797722
I took the one from the help file and change only the setting to the TreeViewNodeSorter:

' Set the TreeViewNodeSorter property to a new instance
' of the custom sorter.
Private Sub button1_Click(ByVal sender As Object, _
    ByVal e As EventArgs) Handles button1.Click

    With TreeView1
          .BeginUpdate
          .TreeViewNodeSorter = New NodeSorter()
          .EndUpdate
    End With
End Sub 'button1_Click

' Create a node sorter that implements the IComparer interface.

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 tx As TreeNode = CType(x, TreeNode)
        Dim ty As TreeNode = CType(y, TreeNode)
       
        If tx.Text.Length <> ty.Text.Length Then
            Return tx.Text.Length - ty.Text.Length
        End If
        Return String.Compare(ty.Text, tx.Text)

    End Function
End Class
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 96

Expert Comment

by:Bob Learned
ID: 16798235
I did this small test:

        Dim root As TreeNode = Me.TreeView1.Nodes.Add("Root")

        Dim parent As TreeNode = root.Nodes.Add("Parent")

        parent.Nodes.Add("Child 5")
        parent.Nodes.Add("Child 4")
        parent.Nodes.Add("Child 3")
        parent.Nodes.Add("Child 2")
        parent.Nodes.Add("Child 1")

        root.ExpandAll()

        Me.TreeView1.Sort()

So, what you need is to call the Sort method.  If you need to implement a non-standard sort order, such as case-insensitive, descending strings, then you would implement a TreeViewNodeSorter instance, but you would still need to call the Sort method to perform the sort.

Bob
0
 
LVL 70

Author Comment

by:Éric Moreau
ID: 16798437
I have added 2 buttons to a form that contains the treeview.

the first button set the Sorted property to True

the second button set .TreeViewNodeSorter property to New NodeSorter()

When I run, I can click the first button and the list sort alphabetically. I can then click the second button and the nodes are sorted based on their length (as the Compare method sample does). BTW, all that is working without ever calling the Sort() method.

Finally, if I click the first button, nothing happens. As I read from the help file, it should revert back to the alphabetical order.
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 16798463
Confusion:  I don't see a Sorted property.  Is this ASP.NET or WinForms?  Help me get to the same place that you are.

Bob
0
 
LVL 70

Author Comment

by:Éric Moreau
ID: 16798473
Windows forms.

The Sorted property does not appear in the Intellisense but it is working. It is even documented in the help.
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 16798591
Crap!!!  More hidden properties that I need to discover :(

Did you say that it is working now?

Bob
0
 
LVL 70

Author Comment

by:Éric Moreau
ID: 16798611
not at all.

What I try to do is to be able to switch from one method to the other. If we refer to the help, it should be doable:
"After the TreeViewNodeSorter is set, if the Sorted property is set to true, the nodes will be sorted in alphabetical order."
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 16798691
Ok, that looks like a bug with the example.  I changed the NodeSorter to this, and it works:

    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 tx As TreeNode = CType(x, TreeNode)
            Dim ty As TreeNode = CType(y, TreeNode)

            If tx.Text.Length <> ty.Text.Length Then
                Return tx.Text.Length - ty.Text.Length
            End If
            Return String.Compare(tx.Text, ty.Text)

        End Function
    End Class

I transposed tx.Text and ty.Text:

            Return String.Compare(tx.Text, ty.Text)

instead of

            Return String.Compare(ty.Text, tx.Text)

Bob
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 16798699
Now, if you want the default sorting of ascending, case-sensitive, the TreeView already implements a node sorter.

Bob
0
 
LVL 70

Author Comment

by:Éric Moreau
ID: 16798743
Sadly, I can't try it right now (not before tonight).

Are you telling me that if I replace this single line, I will be able to use both buttons (default Sorted property and the new TreeViewNodeSorter property) one after the other and both will work?

The case that was not working for me is:
-click button1 (Sorted = True) - Sorts OK - nodes sorted alphabetically
-click button2 (TreeViewNodeSorter = New NodeSorter()) - Sorts OK - nodes sorted by length
-click button1 (Sorted = True) - Does nothing - nodes still sorted by length
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 16798785
What I am telling you is that I used the NodeSorter that you showed me (that I also saw from MSDN help), and it didn't work for me until I switched the order of those two text elements in the String.Compare call.  I was using the Sorted = True property setting.

Bob
0
 
LVL 70

Author Comment

by:Éric Moreau
ID: 16798853
and are you able to revert to a simple default alphabetical order after you set the TreeViewNodeSorter?

Your nodes are not a perfect test set. You should try with:

        parent.Nodes.Add("Child 55555555")
        parent.Nodes.Add("Child 4")
        parent.Nodes.Add("Child 333")
        parent.Nodes.Add("Child 22")
        parent.Nodes.Add("Child 1111")

If you sort only with Sorted, since it is alphabetical, you should get:
Child 1111
Child 22
Child 333
Child 4
Child 55555555

Then if you sort with TreeViewNodeSorter, you should see the node sorted from the longest to the shortest like this:
Child 55555555
Child 1111
Child 333
Child 22
Child 4

I would then lile to return to first sort (alphabetical order).
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 16798903
When I ran the test without the NodeSorter, I get this:

Child 1111
Child 22
Child 333
Child 4
Child 55555555

With the NodeSorter, I get this:

Child 4
Child 22
Child 333
Child 1111
Child 55555555

This appears to be a numeric sort order, and not a string sort order.

Bob
0
 
LVL 70

Author Comment

by:Éric Moreau
ID: 16798940
>>With the NodeSorter, I get this:
>>This appears to be a numeric sort order

It is from shortest string to longest string because you change
Return String.Compare(ty.Text, tx.Text)
to
Return String.Compare(tx.Text, ty.Text)

up to here, everything is OK.

Now what if you try get back to the first alphabetical sort to return to :
Child 1111
Child 22
Child 333
Child 4
Child 55555555
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 16799088
Nope, changing the order of tx.Text and ty.Text didn't affect the order of the sort, because it never gets to that, since it always passes this check:

    If tx.Text.Length <> ty.Text.Length Then

I tried this:

   parent.Nodes.Add("Child 55555555")
   parent.Nodes.Add("Child 4")
   parent.Nodes.Add("Child 333")
   parent.Nodes.Add("Child 22")
   parent.Nodes.Add("Child 1111")
   parent.Nodes.Add("Child 1011")

and got this with Return String.Compare(tx.Text, ty.Text):

Child 4
Child 22
Child 333
Child 1011
Child 1111
Child 55555555

and this with Return String.Compare(ty.Text, tx.Text):

Child 4
Child 22
Child 333
Child 1111
Child 1011
Child 55555555

Bob
0
 
LVL 70

Author Comment

by:Éric Moreau
ID: 16799126
ok but my main point here is not the Compare class, it is how to get back to the first alphabetical sort to return to :
Child 1111
Child 22
Child 333
Child 4
Child 55555555

I want the user to be able to switch between the default sorting and a custom sorting.
0
 
LVL 70

Author Comment

by:Éric Moreau
ID: 16799672
You didn't had time or you haven't found any solution? That may be a bug or an error in the help file.
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 16799786
Just doing a little investigation with Reflector.

1) Here is the property

    Public Property TreeViewNodeSorter As IComparer
      Get
            Return Me.treeViewNodeSorter
      End Get
      Set(ByVal value As IComparer)
            If (Not Me.treeViewNodeSorter Is value) Then
                  Me.treeViewNodeSorter = value
                  If (Not value Is Nothing) Then
                        Me.Sort
                  End If
            End If
      End Set
End Property

2) When you set the TreeViewNodeSorter to NodeSorter, the control calls the Sort method

3) The Sorted property does this:

Public Property Sorted As Boolean
      Get
            Return Me.treeViewState.Item(128)
      End Get
      Set(ByVal value As Boolean)
            If (Me.Sorted <> value) Then
                  Me.treeViewState.Item(128) = value
                  If ((Me.Sorted AndAlso (Me.TreeViewNodeSorter Is Nothing)) AndAlso (Me.Nodes.Count >= 1)) Then
                        Me.RefreshNodes
                  End If
            End If
      End Set
End Property

4) RefreshNodes does this:

Private Sub RefreshNodes()
      Dim nodeArray1 As TreeNode() = New TreeNode(Me.Nodes.Count  - 1) {}
      Me.Nodes.CopyTo(nodeArray1, 0)
      Me.Nodes.Clear
      Me.Nodes.AddRange(nodeArray1)
End Sub

5) I am trying to find in all that code how it is sorted by default.  It is buried in there somewhere.

Bob
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 16800079
The Sort method does this:

   Public Sub Sort()
      Me.Sorted = True
      Me.RefreshNodes()
   End Sub

How does that work if you haven't set the TreeViewNodeSorter?

Bob
0
 
LVL 70

Author Comment

by:Éric Moreau
ID: 16800466
>>How does that work if you haven't set the TreeViewNodeSorter?

Nodes are sorted alphabetically. In my scenario, it is my button1.
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 16800744
Right, but internally in the control I can't see how nodes are sorted just by clearing and readding nodes.

Bob
0
 
LVL 96

Accepted Solution

by:
Bob Learned earned 2000 total points
ID: 16806548
Eric,

I went back and looked at these steps a little closer:

Button1:
  TreeView1.Sorted = True

Button2:
  TreeView1.TreeViewNodeSorter = New NodeSorter()

Button1:
   TreeView1.Sorted = True

Looking at the Sorted property, nothing happens unless you change the value (If Me.Sorted <> value Then):

Public Property Sorted As Boolean
      Get
            Return Me.treeViewState.Item(128)
      End Get
      Set(ByVal value As Boolean)
            If Me.Sorted <> value Then
                  Me.treeViewState.Item(128) = value
                  If Me.Sorted AndAlso Me.TreeViewNodeSorter Is Nothing AndAlso Me.Nodes.Count >= 1 Then
                        Me.RefreshNodes
                  End If
            End If
      End Set
End Property

In this case, you would have to force the sort with a call to the Sort method, or define your own TreeView control, and override the default behavior of the Sorted property.

Bob
0
 
LVL 70

Author Comment

by:Éric Moreau
ID: 16806754
Bob, you just found it.

I have tried calling the Sort method and setting the TreeViewNodeSorter property to nothing but never togheter!

Here is how the code needs to look like:
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        'This will sort the string from the shortest to the longest
        With TreeView1
            .BeginUpdate()
            .TreeViewNodeSorter = Nothing
            .Sorted = True
            .Sort()
            .EndUpdate()
        End With
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        'This will sort the string from the shortest to the longest
        With TreeView1
            .BeginUpdate()
            .TreeViewNodeSorter = New NodeSorter()
            .EndUpdate()
        End With
    End Sub

0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 16806797
The interesting thing the first time is Sorted = True and Sort will cause the sort to happen twice.

Bob
0
 
LVL 70

Author Comment

by:Éric Moreau
ID: 16806956
here is another way of doing for which we don't need to call the Sort method:

        'This will sort the string from the shortest to the longest
        With TreeView1
            .BeginUpdate()
            If .TreeViewNodeSorter IsNot Nothing Then
                .Sorted = False
                .TreeViewNodeSorter = Nothing
            End If
            .Sorted = True
            .EndUpdate()
        End With
0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Well, all of us have seen the multiple EXCEL.EXE's in task manager that won't die even if you call the .close, .dispose methods. Try this method to kill any excels in memory. You can copy the kill function to create a check function and replace the …
The ECB site provides FX rates for major currencies since its inception in 1999 in the form of an XML feed. The files have the following format (reducted for brevity) (CODE) There are three files available HERE (http://www.ecb.europa.eu/stats/exch…
this video summaries big data hadoop online training demo (http://onlineitguru.com/big-data-hadoop-online-training-placement.html) , and covers basics in big data hadoop .
Is your data getting by on basic protection measures? In today’s climate of debilitating malware and ransomware—like WannaCry—that may not be enough. You need to establish more than basics, like a recovery plan that protects both data and endpoints.…

850 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question