ToolStripDropDown sortieren mit Linq

  • VB.NET

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    ToolStripDropDown sortieren mit Linq

    Hallöchen,

    ich habe ein

    Quellcode

    1. ToolStripDropDown
    und wollte diesen gerne sortieren. Ich dachte, da es kein OrderBy zur Auswahl gibt, ich könnte mit Linq hantieren aber dafür fehlt mir wohl einfach noch das Verständnis.
    Wie muss ich da vorgehen? (Wenn es denn geht?)

    VB.NET-Quellcode

    1. TSDD_Hinweislisten.DropDownItems.OfType(Of ToolStripDropDown()).OrderByDescending(Function(n) n)


    Freue mich über eine Rückmeldung.
    Das funktioniert aus mehreren Gründen nicht so, wie Du denkst.
    Deine LINQ-Zeile gibt Dir ne Auflistung wieder. Sie führt aber selber zu keinen Veränderungen.
    .OrderByDescending(Function(n) n): Du nimmst als Sortierkriterium das Item selber her. Woher soll der Compiler wissen, was da nun vor dem anderen kommt, also wie sowas sortiert werden soll? Nach Name? y-Koordinate? Farbton? Textlänge? Daher auch die Frage an Dich: Wonach soll denn sortiert werden?
    Um dann die tatsächliche Sortierung anzuwenden, musst Du wohl im ParentControl, also wohl TSDD_Hinweislisten die Items/Child-Controls rauslöschen und sie dann einfügen, dann wohl mithilfe der LINQ-Ergebnisliste. Aber nur LINQ allein hilft Dir nicht weiter.
    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.
    Wie oben beschrieben. LINQ gibt die zwar ne sortierte Liste wieder, aber die musst Du eben weiterverwenden verwenden, um die Controls/Items in Deinem ToolStripDropDown neu anzuordnen, in Sinne von:

    VB.NET-Quellcode

    1. Dim DeineSortierteListe = TSDD_Hinweislisten.DropDownItems.OfType(Of ToolStripDropDown()).OrderByDescending(Function(n) n)
    2. ToolStripDropDown.Controls.Clear
    3. ToolStripDropDown.Items.Add(DeineSortierteListe)

    Keine Ahnung, ob das von den Befehlen her so für das ToolStripDropDown klappt, da ich das jetzt noch nicht nachgebaut habe, aber vom Prinzip her schon.

    Aber was meinst Du mit "nach Namen sortieren"? Die CE-Namen jucken doch den User nicht? Ob die jetzt ToolStripButton1, ToolStripButton2, ToolStripButton3 oder TsiBtnSave, TsiBtnOpen, TsiBtnClose heißen. Oder geht es Dir um die Beschriftung?
    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.
    Dann musst Du bei LINQ ebendiese als Sortierkriterium verwenden. Probier's mal mit TSDD_Hinweislisten.DropDownItems.OfType(Of ToolStripDropDown()).OrderByDescending(Function(n) n.Text)
    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.
    @VaporiZed

    VB.NET-Quellcode

    1. Dim liste = TSDD_Hinweislisten.DropDownItems.OfType(Of ToolStripDropDown()).OrderByDescending(Function(n) n.ToString)
    2. TSDD_Hinweislisten.DropDownItems.Add(liste)


    Es klappt so leider nicht und mit der Fehlermeldung, werde ich irgendwie nicht grün.

    Spoiler anzeigen

    System.Reflection.AmbiguousMatchException: "Fehler beim Auflösen der Überladung. Kein Public Add kann mit diesen Argumenten aufgerufen werden:
    'Public Function Add(text As String) As System.Windows.Forms.ToolStripItem':
    Der mit dem Argument übereinstimmende Parameter text kann nicht von OrderedEnumerable(Of ToolStripDropDown(),String) in String konvertieren.
    'Public Function Add(image As System.Drawing.Image) As System.Windows.Forms.ToolStripItem':
    Der mit dem Argument übereinstimmende Parameter image kann nicht von OrderedEnumerable(Of ToolStripDropDown(),String) in Image konvertieren.
    'Public Function Add(value As System.Windows.Forms.ToolStripItem) As Integer':
    Der mit dem Argument übereinstimmende Parameter value kann nicht von OrderedEnumerable(Of ToolStripDropDown(),String) in ToolStripItem konvertieren.."
    Die Ex sagt Dir, dass das Ergebnis von LINQ nicht zur Add-Methode passt. Das LINQ-Ergebnis ist (wahrscheinlich) ein IEnumerable(Of ToolStripMenuItem) oder so. Add akzeptiert aber nur ein Element, nicht viele. Gibt's ein AddRange?
    Ok, damit ich da wirklich endgültig helfen kann: Wie bist Du zu Deinem ToolStripDropDown gekommen? Per Designer? Wenn ja, wie genau. Ich find's nicht.

    ##########

    Noch was zu Deinem LINQ: (Function(n) n.ToString): Sicher, dass .ToString das zurückliefert, was Du zum Sortieren brauchst?
    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.
    @VaporiZed

    Ich hatte mir auch das mal angeschaut auf StackOverflow.

    VB.NET-Quellcode

    1. ItemCollection.OfType<ToolStripItem>().OrderBy(x => x.Text).ToArray();


    Ja ein .AddRange gibt es.
    Ich habe einfach ein ToolStrip im Desinger hinzugefügt.
    Nein das .ToString macht es nicht :) aber .Text war nicht zur Auswahl.

    So werden dann die Items im DropDown eingefügt.

    VB.NET-Quellcode

    1. Dim di As DirectoryInfo = New DirectoryInfo(str)
    2. Dim fi As FileInfo()
    3. fi = di.GetFiles("*.pdf", SearchOption.AllDirectories)
    4. Dim fo As FileObject = Nothing
    5. TSDD_Hinweislisten.DropDownItems.Clear()
    6. For i As Integer = 0 To fi.Length - 1
    7. fo = New FileObject()
    8. fo.Name = fi(i).Name
    9. fo.Text = Path.GetFileNameWithoutExtension(fi(i).Name)
    10. fo.Path = fi(i).DirectoryName
    11. With TSDD_Hinweislisten
    12. .DropDownItems.Add(fo)
    13. .DropDownDirection = ToolStripDropDownDirection.AboveRight
    14. End With
    15. AddHandler fo.Click, AddressOf fo_click
    16. Next i



    VB.NET-Quellcode

    1. Dim liste = TSDD_Hinweislisten.DropDownItems.OfType(Of ToolStripDropDown()).OrderByDescending(Function(n) n.ToString)
    2. TSDD_Hinweislisten.DropDownItems.AddRange(liste)


    Damit kommt der Fehler.

    Spoiler anzeigen

    System.Reflection.AmbiguousMatchException: "Fehler beim Auflösen der Überladung. Kein Public AddRange kann mit diesen Argumenten aufgerufen werden:
    'Public Sub AddRange(toolStripItems As System.Windows.Forms.ToolStripItem())':
    Der mit dem Argument übereinstimmende Parameter toolStripItems kann nicht von OrderedEnumerable(Of ToolStripDropDown(),String) in ToolStripItem() konvertieren.
    'Public Sub AddRange(toolStripItems As System.Windows.Forms.ToolStripItemCollection)':
    Der mit dem Argument übereinstimmende Parameter toolStripItems kann nicht von OrderedEnumerable(Of ToolStripDropDown(),String) in ToolStripItemCollection konvertieren.."

    Ok, hab das ToolStripDropDown-Dingens gefunden.
    Also: Das OfType ist insofern falsch, weil Du aus der ToolStripCollection mittels Cast ein ToolStripMenuItem-Array machen musst, da ToolStripDropDowns - wie Du selbst gesehen hast - keine Text-Property haben.
    Desweiteren hast Du das Clear vergessen.
    Und da alle Einträge/Items durch das Clear verschwinden und dann auch nicht mehr zur Verfügung stehen, noch nach dem Sortieren ein .ToList ergänzen, um Kopien zu erhalten. Danach können die Originale gelöscht werden.
    Die AddRange-Funktion nimmt (laut Exception, wie zu lesen) nur ToolStripMenuItems in Array-Form. Dann gib sie ihr mit liste.ToArray

    VB.NET-Quellcode

    1. Dim Liste = TSDD_Hinweislisten.DropDownItems.Cast(Of ToolStripMenuItem).OrderByDescending(Function(n) n.Text).ToList
    2. TSDD_Hinweislisten.DropDownItems.Clear()
    3. TSDD_Hinweislisten.DropDownItems.AddRange(Liste.ToArray)


    btw: Du musst mich nicht mit der @-Funktion ansprechen. Bisher ist ja kein anderer hier aktiv.
    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.
    Hast recht, geht auch und ist kürzer.
    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.
    @VaporiZed und @ErfinderDesRades

    Super Danke :). Nur damit ich es etwas verstehe.
    Ich muss das Objekt (Control) Casten, damit ich den Typ korrekt konvertieren kann? Oder verstehe ich das falsch?
    Wie würde ich dann das Items deklarieren? Als as Object?
    Weder "das Control" noch "das Object" musst du casten, und auch nicht das Objekt(Control) - was immer ein Objekt(Control) sein mag.
    Mach dir immer genau klar, mit was für Datentypen du hantierst - anders kannst du nie kapieren, was du eiglich codest.

    TSDD_Hinweislisten - welchen Datentyp hat das?

    Und welchen Datentyp hat dann: TSDD_Hinweislisten.DropDownItems?

    Tja, das ist die Kernfrage, um zu verstehen, was .Cast(Of ToolStripMenuItem) dann damit macht.

    Hilfestellung: Video-Tut: Welchen Datentyp hat das Objekt?