Numerisches Sortieren in ListView/Code umschreiben von VB6 zu VB 2005

  • VB.NET

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von soulreafer.

    Numerisches Sortieren in ListView/Code umschreiben von VB6 zu VB 2005

    Hallo,
    ich möchte gern meine Listview numerisch Sortieren. Normalerweise sortiert die Listview meist alphanumerisch.

    Bei vb@rchiv hab ich jetzt für VB6 einen solchen Code gefunden, um das selber zu machen bin ich etwas zu sehr Anfänger.
    Wie kann ich diesen Code den für Visual Basic 2005 umschreiben? Manche Codes und Anweisungen gibt es ja einfach nicht mehr und andere heißen einfach anders. Probleme zeigt mein Programm vor allem bei diesem "hWnd" und bei "String" als Befehl benutzt.

    VB.NET-Quellcode

    1. Private Declare Function LockWindowUpdate Lib "user32.dll" ( _
    2. ByVal hWnd As Long) As Long
    3. Public Sub SortListViewColumn(ByVal Index As Integer, _
    4. ByVal CurrentListView As ListView)
    5. Dim I As Integer
    6. Dim strFormat As String
    7. Dim strData() As String
    8. Dim lRet As Long
    9. On Error GoTo ErrorHandler
    10. ' Benutzerdefinierter Formatstring für die
    11. ' Format-Funktion
    12. strFormat = String(30, "0") & "." & String(30, "0")
    13. ' Automatische Aktualisierung des Fensters sperren
    14. lRet = LockWindowUpdate(CurrentListView.Parent.hWnd)
    15. If lRet = 0& Then
    16. Call MsgBox("Can't lock window " & _
    17. CurrentListView.Parent.hWnd, _
    18. vbOKOnly + vbCritical)
    19. Exit Sub
    20. End If
    21. With CurrentListView
    22. With .ListItems
    23. If (Index > 0) Then ' Sortierung nach Subitems
    24. For I = 1 To .Count
    25. With .Item(I).ListSubItems(Index)
    26. ' Sichern des aktuellen Wertes der
    27. ' Text-Eigenschaft in der Tag-Eigenschaft,
    28. ' ohne einen evtl. Inhalt der Tag-Eigenschaft
    29. ' zu überschreiben
    30. .Tag = .Text & vbNullChar & .Tag
    31. ' Falls die Text-Eigenschaft der SubItems
    32. ' eine Zahl ist, so formatiere mit dem oben
    33. ' definierten Formatstring.
    34. If IsNumeric(.Text) Then
    35. .Text = Format$(CDbl("1" & String$(14, "0")) + CDbl(.Text), strFormat)
    36. End If End With
    37. Next I
    38. Else ' Sortierung nach Mainitem
    39. For I = 1 To .Count
    40. With .Item(I)
    41. ' Sichern des aktuellen Wertes der
    42. ' Text-Eigenschaft in der Tag-Eigenschaft,
    43. ' ohne einen evtl. Inhalt der Tag-Eigenschaft
    44. ' zu überschreiben
    45. .Tag = .Text & vbNullChar & .Tag
    46. ' Falls die Text-Eigenschaft der SubItems
    47. ' eine Zahl ist, so formatiere mit dem oben
    48. ' definierten Formatstring.
    49. If IsNumeric(.Text) Then
    50. .Text = Format$(CDbl(.Text), strFormat)
    51. End If
    52. End With
    53. Next I
    54. End If
    55. End With
    56. ' Sortiere die umformatierten Spalten neu
    57. .SortKey = Index
    58. .Sorted = True
    59. .SortOrder = 1 - .SortOrder
    60. With .ListItems
    61. If (Index > 0) Then ' Sortierung nach SubItem
    62. For I = 1 To .Count
    63. With .Item(I).ListSubItems(Index)
    64. ' Extrahiere den ursprünglichen Inhalt des
    65. ' Subitems aus der Tag Eingeschaft und
    66. ' stelle ihn wieder in die Text-Eigenschaft
    67. ' ein.
    68. strData = Split(.Tag, vbNullChar)
    69. .Text = strData(0)
    70. .Tag = strData(1)
    71. End With
    72. Next I
    73. Else ' Sortierung nach MainItem
    74. For I = 1 To .Count
    75. With .Item(I)
    76. ' Extrahiere den ursprünglichen Inhalt des
    77. ' Subitems aus der Tag Eingeschaft und
    78. ' stelle ihn wieder in die Text-Eigenschaft
    79. ' ein.
    80. strData = Split(.Tag, vbNullChar)
    81. .Text = strData(0)
    82. .Tag = strData(1)
    83. End With
    84. Next I
    85. End If
    86. End With
    87. End With
    88. ' Aufheben der Aktualisierungssperre für das Fenster
    89. lRet = LockWindowUpdate(0&)
    90. Exit Sub
    91. ErrorHandler:
    92. lRet = LockWindowUpdate(0&)
    93. Call MsgBox("Runtime error " & Err.Number & ": " & _
    94. vbCrLf & Err.Description, vbOKOnly + vbCritical)
    95. End Sub

    Nia24 schrieb:

    ich möchte gern meine Listview numerisch Sortieren. Normalerweise sortiert die Listview meist alphanumerisch.

    Den alten VB6 Code würde ich mal lieber vergessen. In .NET gibt es für diesen Zweck die ListViewItemSorter Property

    Vielleicht sagst Du einmal nach welcher Spalte Du sortieren willst und wie das "numerische Sortieren" vorgehen soll. Im oben genannten Link ist auch ein Beispiel, was aber vielleicht noch zu schwierig für Dich sein mag.
    ich schreibe die daten in eine Listview, dort möchte ich numerisch die erste Spalte sortieren, sodass erst die negativen, dann die positiven WErte gezeigt werden. Schwierigkeit ist aber, dass ich beim reinschreiben, die Werte zum Teil verdoppel.
    Also sollen die Werte bereits beim Reinschreiben richtig einsortiert werden.

    Nia24 schrieb:

    Also sollen die Werte bereits beim Reinschreiben richtig einsortiert werden.

    Benutze die Klasse NumericLVSorter aus dem folgenden Beispiel und setze die beiden Properties ListView1.Sorting, ListView1.ListViewItemSorter in Deinem projekt genauso:

    Beispiel für eigenen Listview Sorter

    VB.NET-Quellcode

    1. Option Strict On
    2. ' ListView1 must exist on Form
    3. Class Form1
    4. Private Sub form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    5. ' configure Listview
    6. ListView1.View = View.Details
    7. ListView1.Columns.Add(New ColumnHeader())
    8. Me.ListView1.Columns(0).Text = "Column 0"
    9. ListView1.Columns.Add(New ColumnHeader())
    10. Me.ListView1.Columns(1).Text = "Column 1"
    11. ListView1.Columns.Add(New ColumnHeader())
    12. Me.ListView1.Columns(2).Text = "Column 2"
    13. ' SET SORT
    14. ListView1.Sorting = SortOrder.Ascending
    15. ListView1.ListViewItemSorter = New NumericLVSorter ' the SORTER
    16. ' add some values
    17. ListView1.Items.Add(New ListViewItem(New String() {"9", "A", "B"}))
    18. ListView1.Items.Add(New ListViewItem(New String() {"1", "A", "B"}))
    19. ListView1.Items.Add(New ListViewItem(New String() {"-1", "A", "B"}))
    20. ListView1.Items.Add(New ListViewItem(New String() {"-5", "A", "B"}))
    21. ListView1.Items.Add(New ListViewItem(New String() {"100", "A", "B"}))
    22. End Sub
    23. End Class
    24. ' LV Sorter: sorts 1.column numeric
    25. Class NumericLVSorter
    26. Implements IComparer
    27. Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare
    28. Dim lviX As ListViewItem = CType(x, ListViewItem)
    29. Dim lviY As ListViewItem = CType(y, ListViewItem)
    30. ' compare number in 1. Column
    31. Return CInt(lviX.Text) - CInt(lviY.Text)
    32. End Function
    33. End Class

    danke, in deiner forn funktionierts schon super, jetzt muss ich mir nur noch ne anpassung an meine eingabe überlegen, irgenwie mag er nicht, wenn er nur den ersten wert zum sortieren hat ;)

    Momentan sieht es so aus:

    VB.NET-Quellcode

    1. Option Strict On
    2. Public Class Form1
    3. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    4. MessageBox.Show("Numerik", Application.ProductName, MessageBoxButtons.OK)
    5. 'Geforderte Box mit Informationen
    6. 'anschließend werden die Stützstellen eingegeben
    7. End Sub
    8. Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
    9. End Sub
    10. Private Sub Stützstelle_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Stützstelle.TextChanged
    11. End Sub
    12. Private Sub Funktionswert_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Funktionswert.TextChanged
    13. End Sub
    14. Private Sub Ableitung_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Ableitung.TextChanged
    15. End Sub
    16. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    17. Dim item As New ListViewItem
    18. 'If Ableitung.TextLength > 0 Then
    19. item.Text = Stützstelle.Text
    20. item.SubItems.Add(Funktionswert.Text)
    21. item.SubItems.Add(Ableitung.Text)
    22. Me.ListView1.Items.Add(item)
    23. 'item.Text = Stützstelle.Text
    24. 'item.SubItems.Add(Funktionswert.Text)
    25. 'Me.ListView1.Items.Add(item)
    26. Stützstelle.Text = ""
    27. Funktionswert.Text = ""
    28. Ableitung.Text = ""
    29. 'Else
    30. 'item.Text = Stützstelle.Text
    31. 'item.SubItems.Add(Funktionswert.Text)
    32. 'item.SubItems.Add(Ableitung.Text)
    33. 'Me.ListView1.Items.Add(item)
    34. 'Stützstelle.Text = ""
    35. 'Funktionswert.Text = ""
    36. 'Ableitung.Text = ""
    37. 'End If
    38. ' SET SORT
    39. ListView1.Sorting = SortOrder.Ascending
    40. ListView1.ListViewItemSorter = New NumericLVSorter ' the SORTER
    41. End Sub
    42. Private Sub ListView1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListView1.SelectedIndexChanged
    43. End Sub
    44. Private Sub Button2_Wechsel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    45. check = True
    46. Me.Hide()
    47. Form2.Show()
    48. End Sub
    49. End Class
    50. ' LV Sorter: sorts 1.column numeric
    51. Class NumericLVSorter
    52. Implements IComparer
    53. Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare
    54. Dim lviX As ListViewItem = CType(x, ListViewItem)
    55. Dim lviY As ListViewItem = CType(y, ListViewItem)
    56. ' compare number in 1. Column
    57. Return CInt(lviX.Text) - CInt(lviY.Text)
    58. End Function
    59. End Class
    Hi Nia24!
    Versuche doch bitte, beim Posten des Quellcodes die leeren (=unnötigen) Subs sowie unnötige Leerzeilen wegzulassen.
    Das macht es allen einfacher, diese Codes zu lesen. Außerdem ist bei längeren Codesequenzen der Expander zu empfehlen.
    dein Code um 30 Zeilen kürzer

    VB.NET-Quellcode

    1. Option Strict On
    2. Public Class Form1
    3. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    4. MessageBox.Show("Numerik", Application.ProductName, MessageBoxButtons.OK)
    5. 'Geforderte Box mit Informationen
    6. 'anschließend werden die Stützstellen eingegeben
    7. End Sub
    8. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    9. Dim item As New ListViewItem
    10. 'If Ableitung.TextLength > 0 Then
    11. item.Text = Stützstelle.Text
    12. item.SubItems.Add(Funktionswert.Text)
    13. item.SubItems.Add(Ableitung.Text)
    14. Me.ListView1.Items.Add(item)
    15. 'item.Text = Stützstelle.Text
    16. 'item.SubItems.Add(Funktionswert.Text)
    17. 'Me.ListView1.Items.Add(item)
    18. Stützstelle.Text = ""
    19. Funktionswert.Text = ""
    20. Ableitung.Text = ""
    21. 'Else
    22. 'item.Text = Stützstelle.Text
    23. 'item.SubItems.Add(Funktionswert.Text)
    24. 'item.SubItems.Add(Ableitung.Text)
    25. 'Me.ListView1.Items.Add(item)
    26. 'Stützstelle.Text = ""
    27. 'Funktionswert.Text = ""
    28. 'Ableitung.Text = ""
    29. 'End If
    30. ' SET SORT
    31. ListView1.Sorting = SortOrder.Ascending
    32. ListView1.ListViewItemSorter = New NumericLVSorter ' the SORTER
    33. End Sub
    34. Private Sub Button2_Wechsel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    35. check = True
    36. Me.Hide()
    37. Form2.Show()
    38. End Sub
    39. End Class
    40. ' LV Sorter: sorts 1.column numeric
    41. Class NumericLVSorter
    42. Implements IComparer
    43. Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare
    44. Dim lviX As ListViewItem = CType(x, ListViewItem)
    45. Dim lviY As ListViewItem = CType(y, ListViewItem)
    46. ' compare number in 1. Column
    47. Return CInt(lviX.Text) - CInt(lviY.Text)
    48. End Function
    49. End Class

    ich ab jetzt ne weile damit rumprobiert, aber immer noch ein problem.
    zweitens: hab ich keine ahnung,aber es kommt immer, wenn ich es laufen lasse:
    "Ungültige Konvertierung von der Zeichenfolge in Typ Integer." bei der Zeile 59/96.
    im moment lasse ich werte eingeben und sobald der zweite wert kommt, soll sortiert werden, dabei stoppt das programm und zeigt die invalidcastexception an.
    kann das an "option strict on" liegen?

    Nia24 schrieb:

    kann das an "option strict on" liegen

    Nein, die Option Strict On verhindert sogar eher Laufzeitfehler , indem sie auf mögliche Konvertierungsfehler während des Designs hinweist.

    Dein Problem wird eher sein, dass Du in der Spalte 0 einen Wert hast der nicht in einen Integer - Wert umgewandelt werden kann. Entweder einen Leerstring (="") oder einen nichtnumerischen String. Damit kommt in Zeile 96 eine Laufzeit-Exception.

    Die beiden Zeilen

    VB.NET-Quellcode

    1. ' SET SORT
    2. ListView1.Sorting = SortOrder.Ascending
    3. ListView1.ListViewItemSorter = New NumericLVSorter ' the SORTER

    sollten übrigens in das Form-Load Event der Form. Der NumericSorter sorgt schon beim Einsetzen eines neuen Wertes für die richtige Sortierung.
    den hab ich schon versucht, leider hatte ich da etwas mehr probleme.
    Ich vermute, dass es an einer Leerzeile in der Listview liegt, diese ist bereits von Anfang an drin und ich hab sie noch nicht raus bekommen. habt ihr da noch eine IDee?

    Andere Frage noch, die WErte sind eigentlich Double-WErte, aber durch Option Strict on will es diese dauernd in Integer WErte konvertieren, dabei wird ja aber gerundet, die Werte werden falsch. Kann ich das Irgendwie verhindern?

    SystemUnknow schrieb:

    hier hast noch ein Beispiel...vieleicht kriegst den zum laufen:
    activevb.de/cgi-bin/tippupload…h_String_Numeric_DateTime


    den link haste mir ja auch in einem thema gegeben. kannst du mir ggf sagen wie ich auf die classe zugreife ohne auf den column der entsprechenden spalte klicken zu müssen.
    denn ich will das sortieren iwie automatisieren per formload oder button.

    sprich spalte 1 enthält zahlen mit dem die sortierung nichts anfangen kann. spalte 2 besitzt durchnummerierte zahlen . aber ich bekomm mit den ganzen hier angebotenen vorschlägen nur spalte 1 sortiert.