Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
[gelöst] Generic List - Dynamische Suche/Filter
trib
myCSharp.de - Member



Dabei seit:
Beiträge: 702

Themenstarter:

[gelöst] Generic List - Dynamische Suche/Filter

beantworten | zitieren | melden

Hallo zusammen,

des öfteren bin ich auf das Problem gestoßen, dass ich ein DGV und ein Databinding habe und mit einer List<T> fülle.
Nun möchte ich natürlich auch eine Filter- & Suchfunktion integrieren.

Die Möglichkeit die BindingSource mit Find oder Filter zu verwenden schlägt fehl, da es sich nicht um eine iBindingList handelt.

Nun kann ich natürlich

myFooList.Find(item => item.Name.Contains("Test123"));
benutzen. Der Nachteil ist allerdings, dass ich dies nun für jede Spalte im DGV einzeln machen darf.
Bisher habe ich auf meiner Suche nach einer einigermaßen eleganten Lösung nichts adequates gefunden.

Es sei noch gesagt, dass ich die Liste aus einem Webservice erhalte und daher etwas eingeschränkt bin.

Gruß,
trib

[EDIT] gelöst
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von trib am .
private Nachricht | Beiträge des Benutzers
Wax
myCSharp.de - Member

Avatar #avatar-2276.jpg


Dabei seit:
Beiträge: 730
Herkunft: Dortmund

beantworten | zitieren | melden

Hi trib,

was spricht denn dagegen einfach eine BindingList zu nehmen? :-)

MfG
wax
private Nachricht | Beiträge des Benutzers
Siedlerchr
myCSharp.de - Member



Dabei seit:
Beiträge: 178
Herkunft: NRW

beantworten | zitieren | melden

Eine normale BindingLst kannst du im DGV aber nicht sortieren. Hatte vor kurzem das selbe Problem.
Für das Sortieren über das Datagrid brauchst du eine SortableBindingLIst wie z.B. Hier:
Sortable BindingList

Für das Filtern würde ich mir mal folgendes anschauen, das erzeugt dynamisch eine Filteroberfläche mit allen Spalten.

Dynamic DataGridView filtering in C#

Das jeweilige Filtern habe ich dann für alle Spalten jeweils einzeln gemacht.

 userList =
                                    new SortableBindingList<Benutzer>(
                                        userList.Where(x => x.Name1.ToUpperInvariant().StartsWith(
                                            f1.Value.ToUpperInvariant())));
                                dgvData.DataSource = userList;

Da hatte ich auch keine gescheite Lösung für gefunden.

Hoffe das bringt dich vielleicht schonmal etwas weiter.

//Edit: Link korrigiert
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von Siedlerchr am .
private Nachricht | Beiträge des Benutzers
trib
myCSharp.de - Member



Dabei seit:
Beiträge: 702

Themenstarter:

beantworten | zitieren | melden

Hallo Wax,

das umstellen der List bewirkt leider auch, dass Funktionen wie AddRange, Find oder FindAll nicht mehr vorhanden sind. Anderer Typ, andere Funktionen :(

Hallo Siedlerchr,

der Link funktioniert leider immer noch nicht ;)
Denke du meinst das hier: Dynamic Filtering in C
Damit hatte ich auch meine liebe Mühe, da dem DataGridView das "verkehrte" Binding zu Grunde liegt und dann beim Auseinandernehmen der Header und Zellen mehrere Konvertierungsfehler geworfen hat. Weiß natürlich nicht mehr alle im einzelnen, aber das hatte auch meist damit zu tun, dass es auch keine iBindingList ist, oder der Typ hinter dem DataBinding keine DataTable war...

Das ähnelt dann meiner aktuellen Lösung:


private void fooDataGridView_KeyDown(object sender, KeyEventArgs e)
        {
                    switch (fooDataGridView.Columns[currentColumn].DataPropertyName)
                    {
                        case "Customer_No":                            
                            InputValue = Input(fooDataGridView.Columns[currentColumn].HeaderText, cellValue);
                            fooBindingSource.DataSource = fooList.FindAll(sq => sq.Customer_No == InputValue);
                            break;                        
                        case "No":
                            InputValue = Input(fooDataGridView.Columns[currentColumn].HeaderText, cellValue);
                            fooBindingSource.DataSource = fooList.FindAll(sq => sq.No == InputValue);
                            break;
[...]
                                            }
}

Wobei "Input" ein Fenster anzeigt um einen Text einzugeben.
private Nachricht | Beiträge des Benutzers
Siedlerchr
myCSharp.de - Member



Dabei seit:
Beiträge: 178
Herkunft: NRW

beantworten | zitieren | melden

Hallo,

ich verwende bei mir folgende SortableBindingList

SortableBindingLIst

Interessant dabei dürfte für dich der Abschnitt hier sein:

private void CreateOrderByMethod(PropertyDescriptor prop, 
                 string orderByMethodName, string cacheKey) {

        /*
         Create a generic method implementation for IEnumerable<T>.
         Cache it.
        */

        var sourceParameter = Expression.Parameter(typeof(List<T>), "source");
        var lambdaParameter = Expression.Parameter(typeof(T), "lambdaParameter");
        var accesedMember = typeof(T).GetProperty(prop.Name);
        var propertySelectorLambda =
            Expression.Lambda(Expression.MakeMemberAccess(lambdaParameter, 
                              accesedMember), lambdaParameter);
        var orderByMethod = typeof(Enumerable).GetMethods()
                                      .Where(a => a.Name == orderByMethodName &&
                                                   a.GetParameters().Length == 2)
                                      .Single()
                                      .MakeGenericMethod(typeof(T), prop.PropertyType);

        var orderByExpression = Expression.Lambda<Func<List<T>, IEnumerable<T>>>(
                                    Expression.Call(orderByMethod,
                                            new Expression[] { sourceParameter, 
                                                               propertySelectorLambda }),
                                            sourceParameter);

        cachedOrderByExpressions.Add(cacheKey, orderByExpression.Compile());
    }

Zitat
In a Nutshell

If, for instance, you create a MySortableBindingList<Sale> and sort on the Customer property, an expression that conceptually looks something like Enumerable.OrderBy<Sale>(originalList, a => a.Customer) will be created and used to do the sorting.

Das könnte doch eigentlich genau das sein was du brauchst. Der Code erzeugt dynamisch eine Lambda Expression, wenn ich das richtig verstanden habe und sortiert dann damit.
private Nachricht | Beiträge des Benutzers
FZelle
myCSharp.de - Experte



Dabei seit:
Beiträge: 10.006

beantworten | zitieren | melden

Naja, wenn du ein kleines bisschen hier gesucht hättest wäre dir bestimmt der Begriff IBindingListView über den weg gelaufen.
private Nachricht | Beiträge des Benutzers
trib
myCSharp.de - Member



Dabei seit:
Beiträge: 702

Themenstarter:

beantworten | zitieren | melden

Zitat von FZelle
Naja, wenn du ein kleines bisschen hier gesucht hättest wäre dir bestimmt der Begriff IBindingListView über den weg gelaufen.

Hallo FZelle,

ich würde schon behaupten dass ich vorher ordentlich gesucht habe. Aber vielleicht ist man manchmal auch zu sehr auf eine Richtung fixiert...

Mit dem Stichwort in der Tasche und dem bereits gefundenen Filter, konnte ich nun eine (zugegebenermaßen etwas umfangreiche) Lösung finden.
Zum einen habe ich nun eine Klasse BindingListView von SourceForge und zum anderen den dynamicGridFilter

Nun übergebe ich der BindingSource des DGV nicht meine Liste, sondern konvertiere diese vorher:

BindingListView<foo> view = new BindingListView<foo>(fooList);
fooBindingSource.DataSource = view;
Dann kann ich auch einfach das DGV an den Filter übergeben :)

Scheint in meinen ersten Tests alles nun problemlos zu funktionieren. Suchen und Filtern ist dann anhand der standard Bordmittel der BindingSource möglich.

Vielen Dank an alle, ihr habt mich in die richtige Richtung geschubst :)
private Nachricht | Beiträge des Benutzers