Listbox Numerische Sortierung Umkehren

  • VB.NET

Es gibt 16 Antworten in diesem Thema. Der letzte Beitrag () ist von ~blaze~.

    Listbox Numerische Sortierung Umkehren

    Hallo liebe Forum Community :)

    Ich habe eine kleine Frage, und zwar trage ich in einem Sub bestimmte Zahlenwerte (Datentyp: Single) in eine Listbox ein. Diese möchte ich nun jedes mal wenn ein neuer Wert hinzugefügt wird sortieren. Dafür hat VB ja die Listbox-Eigenschaft "Sorted", jedoch wenn ich diese auf "True" setze sortiert er die Zahlen absteigend. (Also es fängt mit der kleinsten Zahl oben an)

    Ich möchte diese Sortierung gerne umkehren, da ich den höchsten Wert immer oben haben will.

    Bei Google habe ich dazu als Lösung öfters Arrays gehört, jedoch hab ich nur Code-Snippets für Alphabetische Sortierung gefunden.

    Ich kann mir einfach nicht vorstellen, dass es so umständlich ist eine Sortierung umzudrehen ^^
    Ich hoffe ihr könnt mir helfen & danke im Vorraus!

    ~blaze~ schrieb:

    Hi
    besser an eine SortedList binden. @markus-obi:s Weg ist eher unschön, da eben jede Liste kopiert werden muss.

    Gruß
    ~blaze~


    Wäre es möglich, dass du mir ein kleines Beispiel gibts, wie ich das machen kann?

    Einfach eine neue SortedList deklarieren, an die Listbox binden und die Items reinfüllen? Wir sortiere ich das dann desceding ? Bitte kleines Beispiel..
    Falsch gedacht, mein Programm würde nicht funktionieren, da SortedLIST keine ILIST ist. Wie ich diese Benennungen doch liebe...
    Ich versuch' mich mal an einer Klasse dafür, wenn nicht sonst jemand eine Idee hat.
    Btw. brauchst du die Beiträge nicht zu kopieren, wenn sie direkt darüberstehen.

    Gruß
    ~blaze~
    Erwartet eine BindingSource nicht eine DataSource, die IBindingList, bzw. die SortProperty implementiert, damit eine Sortierung stattfinden kann?

    Das hier funktioniert auf jeden Fall nicht...

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private _bS As New BindingSource
    3. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    4. _bS.Sort = "TheValue DESC"
    5. End Sub
    6. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    7. _bS.Add(New ValueHolder With {.TheValue = 1.44})
    8. _bS.Add(New ValueHolder With {.TheValue = 2.15})
    9. _bS.Add(New ValueHolder With {.TheValue = 1.84})
    10. _bS.Add(New ValueHolder With {.TheValue = 0.44})
    11. _bS.Add(New ValueHolder With {.TheValue = 2.44})
    12. ListBox1.DataSource = _bS
    13. ListBox1.DisplayMember = "TheValue"
    14. End Sub
    15. End Class
    16. Public Class ValueHolder
    17. Public Property TheValue As Single
    18. End Class


    VB.NET-Quellcode

    1. _bS.SupportsSorting


    gibt jedenfalls False zurück...
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Lässt sich das denn nicht "unsauber" bewerkstelligen, ohne die Listbox zu binden?

    VB.NET-Quellcode

    1. Dim arr(ListBox1.Items.Count - 1) As Object
    2. ListBox1.Items.CopyTo(arr, 0)
    3. Array.Reverse(arr)
    4. ListBox1.Items.Clear()
    5. ListBox1.Items.AddRange(arr)


    Ich hatte erst an so etwas gedacht. Aber da hab ich dann am Ende komischerweise ne leere Listbox ?(
    Eine wirklich unsaubere Lösung ist das da:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private _listValues As New List(Of Single)
    3. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    4. _listValues.AddRange({1.33, 3.55, 1.03, 1.99, 3.44})
    5. ListBox1.DataSource = _listValues
    6. End Sub
    7. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    8. SortList()
    9. End Sub
    10. Private Sub SortList()
    11. _listValues.Sort(Function(s1, s2) s2.CompareTo(s1))
    12. ListBox1.DataSource = Nothing
    13. ListBox1.DataSource = _listValues
    14. End Sub
    15. End Class


    Hier musst Du nach dem Sortieren die DataSource-Property auf Nothing setzten und danach gleich wieder an die jetzt sortierte Liste binden. Wird ein Element der Liste hinzugefügt, so muss der Vorgang immer wieder wiederholt werden. Kommt halt sehr darauf an, wie viele Werte Du handhaben willst.

    Ich würd, als saubere Lösung, soweit gehen und das alles in ein DataSet packet und ein DGV zur Anzeige verwenden. Aber ob das nicht etwas overkill wäre. Kommt eben auf den Verwendungszweck an.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Habe hier noch eine halbfertige Lösung:

    VB.NET-Quellcode

    1. Public Class SortedList(Of T As IComparable)
    2. Inherits List(Of T)
    3. 'andere Methoden müssten auch noch abgeändert werden (z.B. insert müsste 'deaktiviert' werden, etc)...
    4. Public Overloads Sub AddRange(collection As System.Collections.Generic.IEnumerable(Of T))
    5. For Each i In collection
    6. Add(i)
    7. Next
    8. End Sub
    9. Public Overloads Sub Add(ByVal item As T)
    10. 'Hier kann noch viel optimiert werden: Da die Liste sortiert ist könnte man eine Binärsurche implementieren.
    11. For i = 0 To Count - 1
    12. If not isBigger(MyBase.Item(i), item) Then
    13. Insert(i, item) 'sortiert einfügen
    14. Exit Sub
    15. End If
    16. Next
    17. MyBase.Add(item) 'am schluss hinzufügen
    18. End Sub
    19. Private Function isBigger(ByVal a As T, ByVal b As T) As Boolean
    20. Return (a.CompareTo(b) > 0)
    21. End Function
    22. End Class


    VB.NET-Quellcode

    1. Dim liste As New SortedList(Of Integer)
    2. liste.Add(128)
    3. liste.Add(0)
    4. liste.AddRange({48, 1, 7, 1, 2, 1})
    5. liste.Add(234)
    6. ListBox1.DataSource = liste


    Einfach die List(of T) dazu bringen die Items automatisch sortiert einzufügen. Alternativ müsste man die Liste komplett neu aufsetzten aber mit Enumeratoren etc hab ich noch nie hantiert... Quick&Dirty und nicht ganz fertig! Ansonsten lässt sich das Ding aber wie eine normale List(of T) verwenden.

    Auch wäre es sinnvoll die Klasse so zu erweitern, dass sie eine auf- und absteigende Sortierung unterstütz. Verändert man die Sortierungsart, so muss die Liste 'umgekippt' werden und isBigger invertiert werden, damit neue Items an der richtigen Stelle eingefügt werden...
    lg
    Bin auch eben mehr oder weniger fertig geworden. Meins ist mit binärer Suche und halt 'ne echte BindingList. Habe jetzt aber ehrlich gesagt keine Lust mehr auf mehr Testing. Hab's so grob angetestet und jetzt gerade noch INotifyPropertyChanged implementiert, aber nicht mehr getestet, ob's wirklich funktioniert. Sortieren und Kommentieren tu' ich ggf. noch wann anders, dann landet's vmtl. auch beim BindingListFilter im Sourcecode-Austausch.

    Gruß
    ~blaze~
    Dateien

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „~blaze~“ ()

    Kann man ja immer mal brauchen. Ich hoffe mal, es funktioniert. Hier btw. einer der Test-Codes:

    VB.NET-Quellcode

    1. Private _underlyingList As DynamicBindingList(Of String)
    2. Private Sub Form_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    3. _underlyingList = New DynamicBindingList(Of String)() 'Liste initialisieren und der DataSource zuweisen
    4. _listBox.DataSource = _underlyingList
    5. End Sub
    6. Private Sub _redButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles _redButton.Click
    7. _underlyingList.Add(_inputTextBox.Text) 'Text hinzufuegen
    8. End Sub
    9. Private Sub _enableSortingButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles _enableSortingButton.Click
    10. _underlyingList.Comparer = StringComparer.CurrentCultureIgnoreCase 'irgendeinen comparer setzen, der die Items direkt sortiert
    11. End Sub


    Das beste: man hätte es zumindest starten sollen. Mit der Observation kommts jetzt zu 'nem Fehler.

    Gruß
    ~blaze~

    SpaceyX schrieb:

    Erwartet eine BindingSource nicht eine DataSource, die IBindingList, bzw. die SortProperty implementiert, damit eine Sortierung stattfinden kann?

    Shit, ja, du hast recht.
    womit wir wieder beim typisierten Dataset wären, weil typDataTable unterstützt solch Zeug.
    So, hab's neu hochgeladen. Was btw. am längsten gedauert hat, war die binäre Suche für Listen mit left < item < right. Hatte da 'ne 0 stehen, wo ein Count hingehört hat. :P
    Edit: mir ist gerade noch eingefallen, dass ich nicht auf Referenzen überprüfe, sondern auf Equals, daher dürfte es bei der Observation Probleme geben, wenn mehrere Werte gleich sind, aber die Referenzen verschieden.

    Gruß
    ~blaze~

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „~blaze~“ ()

    Im Prinzip geht es schon so, wie du es machen wolltest, aber das ist im Prinzip schwerer. Erwarte jetzt nicht, dass du den Code verstehst, wenn du noch nie damit gearbeitet hast, das ist nicht ganz trivial. Der Vorteil vom verwendeten Verfahren ist halt, dass sich die ListBox an die Daten anpasst und nicht die Daten aus der ListBox ermittelt werden. Also musst du selber nicht auf ListBox.Items operieren, sondern du veränderst die der ListBox zugrundeliegende Datenquelle, also die Instanz der DynamicBindingList, mit den Standardoperationen Add, Remove, etc. wie eben oben in dem kleinen Beispiel.
    Der Comparer ist für einen Vergleich der Elemente zuständig. D.h. der sortiert eben die Liste nach ihren Werten unter Verwendung des durch den Comparer definierten Vergleichs. Einfache Comparer sind z.B. für Zahlen, wo halt das linke Argument mit dem rechten verglichen wird (z.B. Compare(3, 4) < 0, Compare(4, 4) = 0, Compare(5, 4) > 0, das sind auch dementsprechend die 3 möglichen Vergleiche, die der Comparer kann, wobei < 0 eben angibt, dass < 0 => l < r, = 0 => l = r, > 0 => l > r).

    Bei Fragen kannst du die nat. gern stellen.

    Gruß
    ~blaze~