BindingSource Filtern mit einer Liste/Array

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

Es gibt 28 Antworten in diesem Thema. Der letzte Beitrag () ist von OliverSte.

    .ChangeBinding, ob nun aus dem FW oder von @ErfinderDesRades, funktioniert nur genau dann, wenn man dies hier NICHT macht:

    VB.NET-Quellcode

    1. ICaBS.Filter = ""


    Sobald man also einen vorher gesetzten Filter mit dem o.a. Kommando wieder entfernt, klappt das mit dem Umbiegen der BS nicht mehr.
    Die Lösung ist zum Glück einfach (wenn man es weiß), statt dessen macht man:

    VB.NET-Quellcode

    1. ICaBS.RemoveFilter()


    Das war's ;)
    Ahh, jetzt muss ich den Thread doch noch mal öffnen.

    Da hab ich also nun einen schönen LINQ Filter gebaut.
    Jetzt möchte ich an die WHERE Klausel noch ein paar Dinge dranhängen, nämlich einen zuvor ermittelten Filter-String.

    VB.NET-Quellcode

    1. filter = $" AND Bemerkung LIKE '%{filterBemerkung.Text}%'"


    und zwar in der Art:

    VB.NET-Quellcode

    1. Dim linqfilter = From ica In ICaDts.ICa Where idMenge.Contains(ica.Id_ICa) And filter


    Geht nicht, "weil strict on keine Konvertierung von String in Boolean zulässt." und aus anderen Gründen.

    Wie parametrisiert man so einen LINQ Ausdruck?

    Alternativ: Wie macht man das, dass sich der LINQ "Filter" und BindingSource.Filter miteinander vertragen? Setzt man nämlich die DataSource der BindingSource auf linqfilter.AsDataView() und versucht darauf .Filter anzuwenden, wird die ursprüngliche DataSource gefiltert :cursing:

    Hurra, ich hab es gefunden:

    VB.NET-Quellcode

    1. ​ICaBS.FilterX(filter, "")

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

    Schau mal das hier:


    dieses ist deine:


    Ich dachte das sind zwei verschiedene Funktionen, weil die eine als Parameter die BindingSource erwartet und die andere nicht. Aber das ist wohl so, wenn man das als Erweiterung nutzt, also mit BS. aufruft.

    Btw, hast du eine Idee, warum das mit dem Filtern so kompliziert ist?
    Wenn ich mit LINQ die neue DataSource an die BindingSource gehängt habe, führe ich noch den FilterX mit weiteren Filter-Kriterien aus aus. Das klappt, soweit es etwas zu filtern gibt. Falls jedoch die FilterX Kriterien in Verbindung mit der LINQ Quelle kein Ergebnis liefern (würden), zeigt das DGV einfach wieder die originale DatasSource mit dem FilterX an. Die vorangegangene Änderung der BindingSource wird also einfach verworfen.

    Beispiel: Habe drei Datensätze mit je einem Wert/Boolean Tupel (25,Ja) , (10, Nein), (17, Ja).
    Mit LINQ filtere ich quasi nach Wert>15, bleiben die beiden mit "Ja". Danach mit .FilterX nach "Nein".
    Ich würde erwarten, dass nichts angezeigt wird, es wird aber der Datensatz (10, Nein) angezeigt!

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

    ja, das ist dieselbe Methode, und ist von mir. Kannst auch mit KontextMenu: "Gehe zu Definition" hingehen.
    Und für Extensions ist die erste Syntax die vorgesehene (weswegen es auch "Extension" heisst). Die 2. Syntax geht aber leider auch.

    Und die entfernt nicht auctomatisch den Filter??
    Ich hätte gedacht, wenn man eine annere DataSource setzt, dass dann ein evtl. vorhandener Filter automatisch hops geht.
    Naja, kann man ja mit leichtigkeit auch noch einbauen.
    Hmm, du hast mich nicht verstanden Ich poste mal gerade den Code und erklärs damit:

    VB.NET-Quellcode

    1. Dim filter As String = "1=1"
    2. If filterICaTyp.SelectedIndex > -1 Then
    3. filter += $" AND ICaTyp='{filterICaTyp.SelectedItem}'"
    4. End If
    5. If filterTage.Text <> String.Empty Then
    6. bFilter.Text = "Alle"
    7. Dim idMenge = From ixm In ICaDts.ICa_x_Melder
    8. Where Not ixm.IsKontaktAmNull AndAlso ixm.IsFeedbackAmNull AndAlso (DateTime.Now() - ixm.KontaktAm) > TimeSpan.FromDays(CDbl(filterTage.Text))
    9. Select ixm.Id_ICa
    10. Dim linqfilter = From ica In ICaDts.ICa Where idMenge.Contains(ica.Id_ICa)
    11. ICaBS.ChangeBinding(linqfilter.AsDataView(), "")
    12. End If
    13. ' Filter setzen
    14. If filter.Length > 3 Then ' es ist neben dem filterTAge noch was anderes gefüllt
    15. Console.WriteLine("Filter: " + filter)
    16. bFilter.Text = "Alle"
    17. ICaBS.FilterX(filter.Substring(8), "")
    18. End If

    Was man vielleicht nicht gleich erkennt, da ist auf dem Form eine Combobox für filterICaTyp und ein Textfeld für filterTage. filterTage wird für den LINQ Teil benutzt. Da werden in einer Childtabelle Datensätze gesucht ...
    filterICaTyp enthält "Ja", "Nein", "Abbruch", oder "Parken" als Strings. Wenn ich die filterTage oder filterICaTyp separat benutze, läuft alles erwartungsgemäß. Sobald ich aber in beiden etwas eintrage, zu dem es kein Ergebnis gibt, findet die LINQ Geschichte keine Beachtung, wird ignoriert. Es wird dann nur der FilterX angewendet!
    Also es werden Datensätze gezeigt, die aufgrund des LINQ Filters nicht gezeigt werden dürften.
    Eine kleine Bilderstrecke, die das verdeutlicht:
    Jo - son Linq2Dataset-Dataview ist nicht recht kompatibel (buggy?) mit den String-Filter-Ausdrücken, wie sie für Bindingsources verwendet werden.
    Ich war damals recht enttäuscht von dem Linq-DataView - es hat auch beim Sortieren rumgesponnen - also klicks mal auf einen SpaltenHeader - dann müsste er eiglich sortieren, vergisst aber gleichzeitig den Linq-Filter.

    Aber Frage: Wenn das Linq-DataView was findet, dann funktioniert die Kombination aus Bindingsource-String und Linq-Filter?

    Wie gesagt: Nach meiner Erfahrung vernichten nachträgliche BindingSource-Einstellungen (Sort oder Filter) die schöne Linq-Filter-Logik.

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

    Hmm, das ist sehr schade, dass das Ding offenbar buggy ist.
    Sortieren im DataView klappt übrigens gut und fehlerfrei.

    Zu deiner Frage.
    Ich setze erst die DataSource auf das LINQ-DataView. Danach den BS-Filter.
    Wenn das LINQ-DataView was findet UND der BS-Filter auch (in der DataView), dann klappt alles.
    Wenn das LINQ-DataView was findet, ABER der BS-Filter NICHT (in der DataView), dann wird NUR der BS-Filter angewendet (auf der original DataSource)!
    Wenn das LINQ-DataView nichts findet, ABER der BS-Filter (in der original DataSource), dann wird NUR der BS-Filter angewendet (auf der original DataSource)!
    Wenn das LINQ-DataView nichts findet und der BS-Filter auch nicht, dann klappt es, es wird nichts angezeigt.

    Es fühlt sich so an: Der BS-Filter sucht nicht in der DataView, sondern in der alten DataSource. Wenn da was ist, wird es gezeigt und die LINQ-DataView verworfen.

    Ein Workaround wäre, den LINQ-Ausdruck mit dem Filterstring zu erweitern. Ich habe schon danach gefragt und gesucht, aber noch keine Lösung dafür erhalten/gefunden.
    Frei nach dem Motto "Hilf dir selbst, sonst hilft dir keiner" (Quelle) habe ich also eine Lösung.
    Nicht super schick, aber funktioniert erst mal.

    Statt einen Stringfilter für die BindingSource aufzubauen, etwa so:

    VB.NET-Quellcode

    1. Dim filter As String = "1=1"
    2. If filterScrJahr.Text <> String.Empty Then
    3. filter += String.Format(" AND ScreeningDatum >= #1/01/{0}# AND ScreeningDatum <= #12/31/{0}#", CShort(filterScrJahr.Text))
    4. End If
    5. If filterICaTyp.SelectedIndex > -1 Then
    6. filter += $" AND ICaTyp='{filterICaTyp.SelectedItem}'"
    7. End If


    und das Ding dann an die BindingSource zu hängen, NACHDEM mit die DataSource derer auf die LINQ-DataView umgebogen wurde, so:

    VB.NET-Quellcode

    1. If filter.Length > 3 Then
    2. ICaBS.FilterX(filter.Substring(8), "")
    3. End If


    kann man doch gleich die LINQ-DataView filtern. Nämlich so:

    VB.NET-Quellcode

    1. Dim linqfilter = From ica In ICaDts.ICa Where idMenge.Contains(ica.Id_ICa)
    2. If filterICaTyp.SelectedIndex > -1 Then
    3. linqfilter = linqfilter.Where(Function(x) x.ICaTyp = filterICaTyp.SelectedItem.ToString)
    4. End If
    5. If filterScrJahr.Text <> String.Empty Then
    6. linqfilter = linqfilter.Where(Function(x) x.ScreeningDatum.Year = CDbl(filterScrJahr.Text))
    7. End If
    8. ICaBS.ChangeBinding(linqfilter.AsDataView(), "")


    Ja und das funktioniert dann auch wie gewünscht. Den BS.Filter braucht man dann gar nicht mehr.
    Nicht schick, weil da noch bisschen was an Prüfungen eingebaut werden muss, dass der Benutzer auch keinen Unfug in die Textfelder zum Filtern eingibt. Soll einem ja nicht alles um die Ohren fliegen.