comboBox.Items.Add aber nur einmal pro Wert

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von mupko.

    comboBox.Items.Add aber nur einmal pro Wert

    Hallo,

    ich möchte in einer Combobox Items hinzufügen welche in einer Liste gespeichert sind.
    Ich möchte aber das jeder Wert nur einmal in der Combobox hinzugefügt wird. Dafür nutze ich diesen Code:

    VB.NET-Quellcode

    1. For Elemente As Integer = 0 To Datensaetze.Count - 1
    2. If comboBox1.FindStringExact(Datensaetze(Elemente).Name) = -1 Then
    3. comboBox1.Items.Add(Datensaetze(Elemente).Name)
    4. End If
    5. Next


    Hierbei habe ich Festgestellt, dass Werte wie "User123" gleich gesetzt wird mit "USER123". Also wird in der ComboBox nur "User123" hinzugefügt, der andere Wert wird ignoriert obwohl er eine andere Schreibweise hat.
    Daher meine Frage, wie bekomme ich beide Einträge in die Combobox?

    In der Liste habe ich aber in der Spalte Name tatsächlich:
    User123
    User123
    USER123
    User123

    In der ComboBox soll jedoch nur:
    User123
    USER123
    erscheinen.
    Danke, mupko
    Vor dem Hinzufügen die Combobox (bzw. Datenquelle) per Schleife durchlaufen und die Einträge vergleichen. Dann ggf. Hinzufügen.
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    Nein nicht ganz.
    In der Liste werden Instanzen einer Klasse verwaltet.
    Die Klasse beinhaltet die Eigenschaften mit Variablen die Strings sind.

    Daher spreche ich diese mit Datensaetze(Index).Name an.
    Also:
    Datensaetze(0).Name = User1"
    Datensaetze(0).Passwort = "---"
    Datensaetze(1).Name = "USER1"
    Datensaetze(1).Passwort= "xxx"

    Das ziel ist nun das alle Werte aus Name jeweils einmalig in der Combobox auftauchen, um Schreibfehler bei bereits erfassten Namen zu vermeiden.
    Danke, mupko
    Tja - Combobox.FindStringExact() tut eben nicht das, was du brauchst, weil ist scheinbar nicht Case-sensitiv (ich habs nicht ausprobiert).
    Also musst du selbst eine FindStringExact()-Methode bauen, die das tut, was du brauchst.
    Ist ja nicht so das Hexenwerk - Combobox.GetItemText(item) ist dein Froind.

    Als Alternative wäre vor allem bei Databinding sinnvoll, die "Dublettenprüfung" auf den angebundenen Daten auszuführen anstatt auf der Combobox.
    Bei voll entwickeltem Databinding - also im Kontext eines relationalen Datenmodell - würde ein Dubletten-Problem womöglich garnet erst auftauchen, denn ein korrekt gebautes relationales Datenmodell ist redundanzfrei.

    Ach - oder eben doch nach dem Prinzip von post#3:

    VB.NET-Quellcode

    1. comboBox1.DataSource = from ds in Datensaetze Select ds.Name Distinct

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Eine Möglichkeit: Bau Dir ne passende LINQ-Extension. Hab zufällig eine im Sortiment. Hier mit Beispiel. Da wird das Distinct eben auf eine Property, nämlich Name angewandt:

    VB.NET-Quellcode

    1. Imports System.Runtime.CompilerServices
    2. Public Class Form1
    3. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    4. Dim Foos As New List(Of Foo)
    5. Foos.Add(New Foo With {.Name = "User123", .Buzz = 42})
    6. Foos.Add(New Foo With {.Name = "USER123", .Buzz = 69})
    7. Foos.Add(New Foo With {.Name = "USER123", .Buzz = 69})
    8. Foos.Add(New Foo With {.Name = "UseR123", .Buzz = 69})
    9. Foos.Add(New Foo With {.Name = "User456", .Buzz = 666})
    10. Foos.Add(New Foo With {.Name = "User789", .Buzz = 8472})
    11. Dim CleanedFoos = Foos.DistinctBy(Function(x) x.Name)
    12. Stop
    13. End Sub
    14. End Class
    15. Public Class Foo
    16. Property Name As String
    17. Property Buzz As Integer
    18. End Class
    19. Public Module Extensions
    20. <Extension> Public Function DistinctBy(Of T, T1)(List As IEnumerable(Of T), Predicate As Func(Of T, T1)) As IEnumerable(Of T)
    21. If List.Count = 0 Then Return New List(Of T)
    22. Dim FinalList As New List(Of T)
    23. For Each ListEntry In List
    24. If Not FinalList.Select(Function(x) Predicate(x)).Contains(Predicate(ListEntry)) Then FinalList.Add(ListEntry)
    25. Next
    26. Return FinalList
    27. End Function
    28. End Module


    ##########

    ErfinderDesRades schrieb:

    Combobox.FindStringExact() tut eben nicht das, was du brauchst, weil ist scheinbar nicht Case-sensitiv

    MSDN schrieb:

    The search performed by this method is not case-sensitive.

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „VaporiZed“ ()

    Hallo,

    ich habe nun eine Lösung gefunden. Ich füge im ersten Schritt alle Werte per For-Schleife in die ComboBox mit:

    VB.NET-Quellcode

    1. For Element As Integer = 0 To Datensaetze.Count - 1
    2. combobox1.Items.Add(Datensaetze(Element).Name)
    3. Next


    im zweiten Schritt habe ich zwei gegenläufige Schleifen, die es ermöglichen das alle Items gelöscht werden welche doppelt gelistet werden:

    VB.NET-Quellcode

    1. Dim suchtext As String
    2. Dim tempText As String
    3. Try
    4. For schleife As Integer = 0 To comboBox1.Items.Count - 1
    5. suchtext = comboBox1.Items(schleife)
    6. For loeschindex As Integer = comboBox1.Items.Count - 1 To 0 Step -1
    7. tempText = comboBox1.Items(loeschindex)
    8. If loeschindex <> schleife Then
    9. If tempText = suchtext Then
    10. cobFilterEintraege.Items.RemoveAt(loeschindex)
    11. End If
    12. End If
    13. Next
    14. Next
    15. Catch ex As Exception
    16. End Try


    Vielleicht nicht das eleganteste, aber für mich zählt das Ergebnis.
    Danke, mupko

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „mupko“ ()

    mupko schrieb:

    Vielleicht nicht das eleganteste
    Wenn du die Property DataSource der Combobox bedienst, geht's ganz einfach --> Hast du dir den Einzeiler in Post #4 schon einmal angeschaut...
    Sonst mach es mit Items zumindest wie unten:

    VB.NET-Quellcode

    1. ComboBox1.Items.AddRange(Datensaetze.Select(Function(d) d.Name).Distinct.ToArray)
    und das war es...
    Schaue dir dazu auch Distinct an...

    PS: Try...Catch brauchst du nicht! --> TryCatch ist ein heißes Eisen

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

    Interessant an post#7 finde ich, dass es einen Ansatz für einen originellen, ziemlich effektiven Dubletten-Eliminier-Algo darstellt, mit der hochlaufenden äusseren Schleife, und der runterlaufenden inneren Schleife.
    Die innere bräuchte auch nicht bis 0 laufen, sondern nur bis zum jeweils äusseren Zähler.
    (Aber ist dem TE glaub nicht wichtig)
    Hallo,

    #9: Doch die innere Schleife muss auf 0 Enden. Wenn man die innere Schleife auf To äußere Schleife setzt dann wird die Comboxox mit immer dem gleichen wert gefüllt und zwar dem des Werts 1 der äußeren Schleife.
    Und den Try-Block brauche ich vorerst, da durch die gegenläufigen Schleifen eine System.ArgumentOutOfRangeException erzeugt wird. Diese aber tatsächlich immer erst nach dem letzten erforderlichen Wewrt in der Combobox.

    #10: Der Code läuft für den Benutzer einwandfrei. Wie gesagt, der Try-Block muss eine System.ArgumentOutOfRangeException abfangen die aber ohne Auswirkung ist. Also nur das Ergebnis zählt.

    Der endgültige Code ist nun:

    VB.NET-Quellcode

    1. Dim suchtext As String
    2. Dim tempText As String 'Dieser Text wird auf Gleichheit mit dem gesuchten Text geprüft.
    3. For Element As Integer = 0 To Datensaetze.Count - 1
    4. Select Case cobFilterSpalten.SelectedIndex
    5. Case 1
    6. cobFilterEintraege.Items.Add(Datensaetze(Element).Anwendungsname)
    7. Case 2
    8. cobFilterEintraege.Items.Add(Datensaetze(Element).Pfad)
    9. Case 3
    10. cobFilterEintraege.Items.Add(Datensaetze(Element).Benutzer)
    11. Case 4
    12. cobFilterEintraege.Items.Add(Datensaetze(Element).Notizen)
    13. End Select
    14. Next
    15. Try
    16. For schleife As Integer = 0 To cobFilterEintraege.Items.Count - 1
    17. suchtext = CStr(cobFilterEintraege.Items(schleife))
    18. For loeschindex As Integer = cobFilterEintraege.Items.Count - 1 To 0 Step -1
    19. tempText = CStr(cobFilterEintraege.Items(loeschindex))
    20. If loeschindex <> schleife Then
    21. If tempText = suchtext Then
    22. cobFilterEintraege.Items.RemoveAt(loeschindex)
    23. End If
    24. End If
    25. Next
    26. Next
    27. Catch ex As Exception
    28. End Try


    Ich lasse also aus cobFilterSpalten den User auswählen was er in CobFilterEintraege sieht.
    Danke, mupko

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „mupko“ ()

    mupko schrieb:

    der Try-Block muss eine System.ArgumentOutOfRangeException abfangen
    Dann sollte
    1. der Catch-Bereich genau diesen Exceptiontyp abfangen, für den Fall, dass weitere Exceptions auftreten, Du aber nix davon mitbekommst, weil Du alles abfängst.
    2. besser: die Exception von vornherein durch korrekte Programmierung verhindert werden, sodass der Try-Catch-Block gar nicht benötigt wird; dazu musst Du natürlich rausfinden, wie es überhaupt soweit kommen kann
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Der Try-Block war mir klar das er nur temporär bleiben wird.

    Der Überlauf entsteht in der äußeren Schleife, da durch das Löschen der Items in der inneren Schleife der Schleifenzähler höher ist als Comboxox.Items.Count -1.
    Ich habe im oberen Code zwischen Zeile 24 und 25 Nachstehenden Code eingebunbden. Der Try-Block ist dann nicht mehr erforderlich.

    VB.NET-Quellcode

    1. ​If schleife > cobFilterEintraege.Items.Count - 1 Then Continue For
    Danke, mupko