none
ListCollectionView mit generischem Filter RRS feed

  • Frage

  • Hallo NG,

    ich verwende derzeit folgende Zeilen um in einer ListviewCollection zu filtern

    this.GeneralDataView = new ListCollectionView(objList);
    this.GeneralDataView.Filter = item => DataTextFilter(item as CarDealerShip);
    ...
    private bool DataTextFilter(CarDealerShip pRowItem) {
    string textFilterString = (this.SearchFilter ?? string.Empty).ToUpper();
    string[] words = textFilterString.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
    foreach (string word in words) {
        //Autohaus, Strasse, 
        // PLZ, Ort, Anrede, Ansprechpartner, 
        //Telefon, Email, ManReportPos, HaendlerGruppe
        bool wordFound = (pRowItem.Autohaus != null && pRowItem.Autohaus.ToUpper().Contains(textFilterString));
        if (!wordFound) {
            return false;
        }
      }
      return (true);
    }

    Nun ist es immer etwas mühselig von der übergebenen Klasse immer alle Properties zu schreiben, die ausgewertet werden sollen. Gibt es eine generische Möglichkeit dazu ?

    Gruß
    Gerhard Ahrens

    Freitag, 13. Dezember 2013 13:55

Antworten

  • Natürlich ist das ganze über Reflection möglich, ich würde es aber eher meiden. Denn erstens denke ich, das die Zugriffe länger dauern und 2. Entsteht ein Tippfehler in einem String viel schneller als im richtigen Quelltext. Dort würde sich ggf. der Compiler melden.

    Wenn du trotz meiner bedenken so etwas realisieren willst, dann hast du hier ein ungetesteten Ansatz:

        class Program
        {
            static void Main(string[] args)
            {
                MyClass mc = new MyClass();//Klasse instanzieren (zum testen)
                mc.CheckValues(//Test-Werte übergeben
                    new CompareObject() { Name = "Property1", Value = "String", IgnoreCaseByStrings = false },
                    new CompareObject() { Name = "Property2", Value = 12, IgnoreCaseByStrings = false },
                    new CompareObject() { Name = "Property3", Value = 15.8M, IgnoreCaseByStrings = false },
                    new CompareObject() { Name = "Property4", Value = MeinObjekt, IgnoreCaseByStrings = false },
                    new CompareObject() { Name = "Property5", Value = "ABC123", IgnoreCaseByStrings = true });
            }
        }
    
        static class Extensions
        {
            public static bool CheckValues(this object obj, params CompareObject[] names)
            {
                foreach (CompareObject name in names)//Alle Vergleiche durch gehen
                {
                    var prop = obj.GetType().GetProperty(name.Name);//Eigenschaft laden
                    var val = prop.GetValue(obj, null);//Wert laden
                    if (prop.PropertyType == typeof(string) && name.IgnoreCaseByStrings)//String ohne Groß-/Kleinschreibung vergleichen
                    {
                        if (val.ToString().ToLower() != name.Value.ToString().ToLower())
                            return false;
                    }
                    else if (val != name.Value)//Objekte vergleichen
                        return false;
                }
                return true;//Alle Werte ok
            }
        }
    
        //Für den Vergleich. zusätzlich noch ein paar Parameter für den Vergleich angeben
        struct CompareObject
        {
            public string Name { get; set; }//Name der Eigenschaft
            public object Value { get; set; }//Value
            public bool IgnoreCaseByStrings { get; set; }//Sonstige Eigenschaften etc.
        }
    Aber hier machst du dir wahrscheinlich nur mehr Arbeit, zumal obiger Aufruf von CheckValues länger wäre als der klassische Vergleich.


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.


    Freitag, 13. Dezember 2013 19:26
    Moderator

Alle Antworten

  • Hallo,
    ich verstehe nicht so ganz, was du vor hast. Meinst du diese Abfrage hier?

    (pRowItem.Autohaus != null && pRowItem.Autohaus.ToUpper().Contains(textFilterString))

    Natürlich kann es aufwendig werden alles eintippen zu müssen, aber woher soll denn eine Methode wissen, was du wann, wo und wie vergleichen willst?

    Generika hat mit dem ganzen auch nur bedingt etwas zu tun. Eventuell ist es möglich eine Erweiterunbgsmethode o.ä. zu schreiben die häufig verwendetes zusammen fasst, aber mehr ist da auch nicht möglich.


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    Freitag, 13. Dezember 2013 15:03
    Moderator
  • Hallo Tom,

    ja, genau den Teil meine ich. Ich dache an Reflection und an eine Liste von Feldern. So eine Konstrukt mit mehr als 5 Properties sieht einfach doof aus. Hmm eine Erweiterungmethode mit einer Liste von Feldern die so ein Ergebnis bringt wäre natürlich auch hilfreich.

    bool ok = (pRowItem.Prop1 != null && pRowItem.Prop1.ToUpper().Contains(textFilterString)) ||

    (pRowItem.Prop2 != null && pRowItem.Prop2.ToUpper().Contains(textFilterString)) ||
    ....


    Ist einfach schwierig zu handhaben. Vor allem wenn dann noch weitere Datetypen dazu kommen
    die immer erst nach String konvertiert werden müssen.
    Danke und Gruß
    Gerhard Ahrens
    Freitag, 13. Dezember 2013 18:46
  • Natürlich ist das ganze über Reflection möglich, ich würde es aber eher meiden. Denn erstens denke ich, das die Zugriffe länger dauern und 2. Entsteht ein Tippfehler in einem String viel schneller als im richtigen Quelltext. Dort würde sich ggf. der Compiler melden.

    Wenn du trotz meiner bedenken so etwas realisieren willst, dann hast du hier ein ungetesteten Ansatz:

        class Program
        {
            static void Main(string[] args)
            {
                MyClass mc = new MyClass();//Klasse instanzieren (zum testen)
                mc.CheckValues(//Test-Werte übergeben
                    new CompareObject() { Name = "Property1", Value = "String", IgnoreCaseByStrings = false },
                    new CompareObject() { Name = "Property2", Value = 12, IgnoreCaseByStrings = false },
                    new CompareObject() { Name = "Property3", Value = 15.8M, IgnoreCaseByStrings = false },
                    new CompareObject() { Name = "Property4", Value = MeinObjekt, IgnoreCaseByStrings = false },
                    new CompareObject() { Name = "Property5", Value = "ABC123", IgnoreCaseByStrings = true });
            }
        }
    
        static class Extensions
        {
            public static bool CheckValues(this object obj, params CompareObject[] names)
            {
                foreach (CompareObject name in names)//Alle Vergleiche durch gehen
                {
                    var prop = obj.GetType().GetProperty(name.Name);//Eigenschaft laden
                    var val = prop.GetValue(obj, null);//Wert laden
                    if (prop.PropertyType == typeof(string) && name.IgnoreCaseByStrings)//String ohne Groß-/Kleinschreibung vergleichen
                    {
                        if (val.ToString().ToLower() != name.Value.ToString().ToLower())
                            return false;
                    }
                    else if (val != name.Value)//Objekte vergleichen
                        return false;
                }
                return true;//Alle Werte ok
            }
        }
    
        //Für den Vergleich. zusätzlich noch ein paar Parameter für den Vergleich angeben
        struct CompareObject
        {
            public string Name { get; set; }//Name der Eigenschaft
            public object Value { get; set; }//Value
            public bool IgnoreCaseByStrings { get; set; }//Sonstige Eigenschaften etc.
        }
    Aber hier machst du dir wahrscheinlich nur mehr Arbeit, zumal obiger Aufruf von CheckValues länger wäre als der klassische Vergleich.


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.


    Freitag, 13. Dezember 2013 19:26
    Moderator
  • Hallo Tom,

    danke für Antwort und Beispiel. Ja auch bei der Programmierung hat alles mehrere Seiten und müssen gut abgewägt werden. Es stimmt was Du zeigst, ich hätte nichts gewonnen.

    Danke und Gruß
    Gerhard Ahrens

    Montag, 16. Dezember 2013 06:26