|
Ist bei einem ListView-Steuerelement aus den Microsoft Common Controls die Eigenschaft Arrange auf "1 - lvwAutoLeft" oder "2 - lvwAutoTop" und die Eigenschaft View auf "0 - lvwIcon" oder "1 - lvwSmallIcon" eingestellt, kann der Anwender die Reihenfolge der Icons durch Verschieben mit der Maus beliebig ändern. Leider haben solche Änderungen keine Auswirkung auf die Reihenfolge in der ListItems-Collection. Auch die Werte der in der Index-Eigenschaft jedes einzelnen ListItems bleibt unverändert. Eine Änderung der Reihenfolge per Code ist offensichtlich nur durch Herausnehmen und Wiedereinfügen an der gewünschten Stelle möglich.
Dennoch gibt es einen Weg, das ListView-Steuerelement zu einer Änderung der ListItems-Reihenfolge zu bewegen. Sie benötigen dazu eine zusätzliche Spalte. Da zusätzliche Spalten in den beiden in Frage kommenden View-Modi gar nicht sichtbar werden, stehen sie Ihnen als Sortierinstrument zur Verfügung. Sie brauchen lediglich jedem ListItem in der entsprechenden Spalte (ListSubItem) einen sortierbaren Wert zuzuweisen und anschließend nach dieser Spalte zu sortieren.
Die zusätzliche(n) Spalte(n) legen Sie entweder gleich zur Entwicklungszeit an, oder Sie legen sie mittels der folgenden LvwCreateIndexKey Funktion an. Dieser übergeben Sie das betreffende ListView und einen Namen für die Sortierspalte (der vorgegebene Standard-Name lautet "posindex" - was es damit auf sich hat, werden Sie später noch sehen).
Public Function LvwCreateIndexKey(ListView As ListView, _
Optional SortColKey As String = "posindex") As Long
Dim nListitem As ListItem
With ListView
With .ColumnHeaders
If .Count = 0 Then
.Add
End If
.Add , SortColKey
End With
For Each nListitem In .ListItems
nListitem.ListSubItems.Add , SortColKey
Next
End With
LvwCreateIndexKey = zGetSortKey(ListView, SortColKey)
End Function
Private Function zGetSortKey(ListView As ListView, _
SortColKey As String) As Long
Dim nHeader As ColumnHeader
For Each nHeader In ListView.ColumnHeaders
With nHeader
If StrComp(SortColKey, .Key, vbTextCompare) = 0 Then
zGetSortKey = .Index - 1
Exit For
End If
End With
Next
End Function
Die Funktion gibt praktischerweise gleich die Nummer des hinzugefügten Sortier- bzw. Spaltenschlüssels zurück, die in der privaten Hilfsfunktion zGetSortKey ermittelt wird. Diese Ermittlung ist in eine separate Funktion ausgelagert, da sie anderweitig auch noch benötigt wird.
Wenn Sie eigene Sortierkriterien haben, weisen Sie dem entsprechenden Spalten-ListSubItem eines ListItems den Sortierwert als Text zu. Die folgende Prozedur LvwListItemSetSortColValue prüft dabei, ob das entsprechende ListSubItem bereits vorhanden ist und fügt es gegebenenfalls hinzu.
Public Sub LvwListItemSetSortColValue(ListItem As ListItem, _
Value As String, Optional SortColKey As String = "posindex")
On Error Resume Next
With ListItem
.ListSubItems(SortColKey).Text = Value
If Err.Number Then
.ListSubItems.Add , SortColKey, Value
End If
End With
End Sub
Umgekehrt liefert Ihnen LvwListItemGetSortColValue den Wert in der Sortierspalte eines ListItems. Diese Funktion sei hier aber eigentlich nur der Vollständigkeit halber passend als Gegenstück zur vorhergehenden Prozedur hier eingefügt:
Public Function LvwListItemGetSortColValue(ListItem As ListItem, _
Optional SortColKey As String = "posindex") As String
LvwListItemGetSortColValue = _
ListItem.ListSubItems(SortColKey).Text
End Function
Das Sortieren anhand der Sortierspalte erledigt LvwSortByIndexKey. Sie geben entweder den Spaltennamen im optionalen Parameter SortColKey an (oder übernehmen die Vorgabe "posindex") und belassen dazu den Wert des nächsten optionalen Parameters SortKey bei -1. Oder Sie geben den nummerischen Index der Spalte an - wobei die Zählung wie bei den Spalten (ColumnHeaders) gewohnt mit 1 beginnt.
Public Sub LvwSortByIndexKey(ListView As ListView, _
Optional SortColKey As String = "posindex", _
Optional ByVal SortKey As Long = -1)
With ListView
If SortKey < 0 Then
.SortKey = zGetSortKey(ListView, SortColKey)
Else
.SortKey = SortKey
End If
.Sorted = True
End With
End Sub
Die beiden folgenden Prozeduren erstellen einfache Sortierspalten, die auf den Inhalten der Text-Eigenschaft oder der Schlüssel der ListItems beruhen.
Public Sub LvwMakeTextIndexKey(ListView As ListView, _
Optional SortColKey As String = "textindex", _
Optional ByVal SortKey As Long = -1)
Dim nListitem As ListItem
With ListView
For Each nListitem In .ListItems
With nListitem
.ListSubItems(SortColKey).Text = .Text
End With
Next
End With
End Sub
Public Sub LvwMakeKeyIndexKey(ListView As ListView, _
Optional SortColKey As String = "keyindex", _
Optional ByVal SortKey As Long = -1)
Dim nListitem As ListItem
With ListView
For Each nListitem In .ListItems
With nListitem
.ListSubItems(SortColKey).Text = .Key
End With
Next
End With
End Sub
Die Eingangs angeführte manuelle Umsortierung durch den Anwender können Sie auch in sortierbare Werte umsetzen und in eine Sortierspalte einfügen. Zur Generierung solcher Werte dienen die Eigenschaften Left und Top der ListItems. Einheitlich 5-stellig formatiert (das reicht in der Regel aus) und zusammengesetzt ergeben sie die aktuell im ListView dargestellte Reihenfolge. Ist in der Arrange-Eigenschaft des ListViews lvwAutoLeft eingestellt, steht der Left-Wert vorne, bei lvwAutoTop steht der Top-Wert vorne. Auch diese Generierung der Sortierwerte können Sie von einer Prozedur erledigen lassen - LvwMakePosIndexKey generiert die Sortierspalte "posindex".
Public Sub LvwMakePosIndexKey(ListView As ListView, _
Optional SortColKey As String = "posindex", _
Optional ByVal SortKey As Long = -1)
Dim nListitem As ListItem
With ListView
Select Case .Arrange
Case lvwAutoLeft
For Each nListitem In .ListItems
With nListitem
.ListSubItems(SortColKey).Text = _
Format$(.Left, "00000") & "-" & Format$(.Top, "00000")
End With
Next
Case lvwAutoTop
For Each nListitem In .ListItems
With nListitem
.ListSubItems(SortColKey).Text = _
Format$(.Top, "00000") & "-" & Format$(.Left, "00000")
End With
Next
End Select
End With
End Sub
|