BindingSource.Filter mit unterschiedlichen Datentypen

  • VB.NET
  • .NET 4.5

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

    Neu

    tragl schrieb:

    Hast du ma probiert ob das Ganze noch funzt wenn du "exakt" angeklickt hast?

    Japp, funzt einwandfrei.

    tragl schrieb:

    Und dann gibt's noch ein Problem mit Zeile 110: FilterX brauch noch den / die Parameter. Hier kannst du dann eher mit Filter = arbeiten.

    klappt auch.

    tragl schrieb:

    das muss MIR nicht helfen, sondern dir aber wir versuchen's erstma so.

    tragl schrieb:

    Ist aber über einen Editor gemacht - also kein IntelliSense. Wär' also vielleicht garnicht so verkehrt mit nem kleinen Demo-Projekt und ner Hand voll Daten.

    Ich habe ja das Hauptprogramm mit Daten und kann lustig rumtesten.
    Ich mache mich mal ran eine Demo zu basteln und gebe laut, wenn ich fertig bin.

    Ah sorry. Auf deine Select Case verschönerung einzugehen, habe ich vergessen.
    Diese habe ich versucht - allerdings wurde bei mir nur die erste Case Anweisung abgearbeitet.
    Wenn also CBArtNo.checked und CBEAN.checked = True sind, springt das Programm in den entsprechenden Case CBArtNo.Checked Zweig und dannach zu End Select.
    CBEAN.Checked (und alle anderen) werden nicht mehr abgearbeitet.

    Neu

    Ich bau solche komplexen Filter immer mit einer List(Of String).
    Also keinen String, der immer länger wird, und man muss immer ein OR dazwischen-frickeln ausser beim ersten Aufruf.
    Sondern meine List(Of String) heisst filterSegments, und da sind FilterAusdrücke drin jeweils für eine Spalte.
    Wenn alle Einflussgrössen abgearbeitet sind (hier: alle Checkboxen), joine ich die filterSegments mit Or dazwischen zusammen und habe einen schönen FilterString.

    VB.NET-Quellcode

    1. '...
    2. Return String.Join(" OR ", filterSegments)'fertigen FilterString returnen

    Ich wiederhols nochmal: Sowas ist eine aufwändige und knifflige und schwer lesbare Programmier-Aufgabe. Mach dir ein UserControl dafür, was sich genau darum kümmert.
    Damit sich das nicht auch noch mit anderen komplizierten Programmteilen vermischt.



    Noch eleganter wirds, wenn du dir eine typisierte DataTable dafür anlegst.
    Dann kannst du in einer Partialen Klasse die Logik implementieren und hast das nicht im Form1-Code rumfahren.
    Du kannst dem Teil eine DataTable übergeben, und es liest die SpaltenNamen aus, und baut Datensätze draus, mit den Spalten SpaltenName und IsChecked.
    Diese Datensätze kannste an ein DGV binden, und kannst wunnebar für jede Spalte eine Checkbox klicken - das wäre dann architektonisch gut strukturiert, und ausserdem anwendbar auf jede mögliche DataTable.
    In der Partialen Klasse gäbe es eine Methode, die die Datensätze auswertet und einen FilterString ausgibt.
    Das Konzept ist auch erweiterbar um verschiedene Arten der Filterung (ja/nein, exakt/Like, Wertebereiche,...)
    aber das ist auch bischen das Rad neu erfinden - Tragl hat ja ein Projekt verlinkt, was ähnliches bereits umgesetzt hat.

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

    Neu

    Hier erstmal die Demo.
    ​ Tragl hat ja ein Projekt verlinkt, was ähnliches bereits umgesetzt hat.

    Japp - an dem Link habe ich aber noch ein bisschen zu knabbern :o)
    Dateien
    • FilterTest.zip

      (296,77 kB, 2 mal heruntergeladen, zuletzt: )

    Neu

    DerSmurf schrieb:

    Diese habe ich versucht - allerdings wurde bei mir nur die erste Case Anweisung abgearbeitet

    jo, so is das wenn man nur mit code hantiert ohne Demo. Hab's jetzt mal ein bisschen aufgehübscht - würde mir für meine persönlichen Zwecke reichen.
    Aber Edr hat recht - wenn man's ordentlich machen wöllte, sollte man sich dafür was komplexes bauen was auch in jeder Anwendung mit jeder DataTable etc. funzt.

    Ist nur immer die Frage, ob man das auch möchte :D
    Also Select Case is nu weg, dafür verkürzte IF-Abfragen und meine Function ist nun eine Sub, dafür kann deine EditSearchString-Sub weg.
    Achja und ich hab noch ein IF THEN ELSE eingebaut, bevor endgültig gefiltert wird. Vorher kam eine Exception, wenn man versehentlich "keine" CheckBox angehakt hat - jetzt nich mehr
    Dateien
    • FilterTest01.zip

      (28,1 kB, 1 mal heruntergeladen, zuletzt: )
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

    Neu

    jo, ich würd so machen:

    VB.NET-Quellcode

    1. Imports System.IO
    2. Public Class Form1
    3. Private _DataFile As New FileInfo("File.xml")
    4. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    5. If File.Exists(_DataFile.FullName) Then
    6. DtsSettings.ReadXml(_DataFile.FullName)
    7. End If
    8. 'DtsSettings.FilterSetting.SetTable(DtsSettings.Article) ' sämtliche Spalten fürs Durchsuchen einrichten
    9. With DtsSettings.Article
    10. DtsSettings.FilterSetting.SetColumns(.ArtNrColumn, .EANColumn, .Name1Column, .Name2Column,
    11. .ListPriceColumn, .DiscountColumn, .PurchasingPriceColumn, .SalesMarginColumn, .RetailPriceColumn, .NoteColumn)
    12. End With
    13. End Sub
    14. Private Sub Form1_Closed(sender As Object, e As EventArgs) Handles Me.Closed
    15. 'DtsSettings.WriteXml(_DataFile.FullName)
    16. End Sub
    17. Private Sub StartArticleSearch()
    18. ArticleBindingSource.Filter = DtsSettings.FilterSetting.GetFilter(TBSearchArticles.Text, ckUngefaehr.Checked)
    19. End Sub
    20. Private Sub TBSearchArticles_TextChanged(sender As Object, e As EventArgs) Handles TBSearchArticles.TextChanged, ckUngefaehr.CheckedChanged, btApply.Click
    21. StartArticleSearch()
    22. End Sub
    23. End Class

    VB.NET-Quellcode

    1. Partial Public Class DtsSettings
    2. Partial Class FilterSettingDataTable
    3. Public Function GetFilter(search As String, useAsterisk As Boolean) As String
    4. Dim segments = From rw In Me Where rw.IsChecked Select rw.GetFilter(search, useAsterisk)
    5. Return String.Join(" OR ", segments)
    6. End Function
    7. Public Sub SetColumns(ParamArray columns() As DataColumn)
    8. Clear()
    9. columns.ForEach(Sub(x) Me.AddFilterSettingRow(x.ColumnName, x.DataType Is GetType(String), False))
    10. End Sub
    11. Public Sub SetTable(tb As DataTable)
    12. Dim fkCols = tb.ParentRelations.Cast(Of DataRelation)().SelectMany(Function(xx) xx.ChildColumns) 'Fremdschlüssel sind nicht durchsuchbar
    13. SetColumns(tb.Columns.Cast(Of DataColumn).Except(fkCols).ToArray)
    14. End Sub
    15. End Class
    16. Partial Class FilterSettingRow
    17. Public Function GetFilter(search As String, useAsterisk As Boolean) As String
    18. Dim asterisk = If(useAsterisk, "*", "")
    19. Dim sCol = If(IsString, Column, $"Convert({Column}, System.String)")
    20. Return $"{sCol} LIKE '{asterisk}{search}{asterisk}'"
    21. End Function
    22. End Class
    23. End Class

    Dateien

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