Laden...

Sortierungsproblem mit BindingSource

Erstellt von UweR vor 17 Jahren Letzter Beitrag vor 17 Jahren 10.819 Views
U
UweR Themenstarter:in
91 Beiträge seit 2004
vor 17 Jahren
Sortierungsproblem mit BindingSource

Hallo Leute,

ich binde ein List<T>-Element mit BindingSource an ein DataGridView. Ist ja auch alles Paletti und wunderhübsch. Nur will sich das Ding nicht sortieren lassen. SupportsSorting ist bei mir false.
Das Element der Liste implementiert IComparable und sollte also vergleichbar sein.

Irgendjemand ne Idee was ich falsch mache?


Gruß
Uwe

4.207 Beiträge seit 2003
vor 17 Jahren

Der Fehler ist, List<> zu verwenden ... damit hatte ich vor kurzem auch zu kämpfen.

Entweder Du baust Dir Deine eigene Sortierung, oder Du stellst auf eine andere Datenquelle um.

Da der Aufwand für eine eigene Sortierung IMHO in keinem Verhältnis zum Ergebnis steht, ist es bei mir nun ein DataSet geworden ...

Insgesamt bin ich von dem DGV ein wenig enttäuscht, das Teil wird angepriesen als die ultimative Lösung für alles mögliche und mit zig tollen neuen Features, und im Kleingedruckten kommt dann wahnsinnig oft der Hinweis, dass es in diesem und jenem Ausnahmefall eben doch nicht ganz so leicht geht ...

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

U
UweR Themenstarter:in
91 Beiträge seit 2004
vor 17 Jahren

Hallo Golo,

danke für den Hinweis. Dann will ich mal alles in ein Dataset umpacken.

Gibts zu diesem DGV-Monstrum eigentlich schon irgendne brauchbare Literatur?


Gruß
Uwe

M
5 Beiträge seit 2006
vor 17 Jahren

Habe das selbe Problem, ist wirklich zum Läuse-Melken!
Brauche ich eine Methode, die die Daten aus meiner List<T> (oder T[], oder ArrayList, klappt alles nicht) in ein DataSet umpackt, oder wie?

Danke,
Matthias

N
4.644 Beiträge seit 2004
vor 17 Jahren

Original von UweR
Dann will ich mal alles in ein Dataset umpacken.

Weshalb? Warum nicht von BindingList ableiten und die Sortierung implementieren? Das machst Du einmal, dann hast Du eine sortierbare Liste für Objekte.

Original von UweR
Gibts zu diesem DGV-Monstrum eigentlich schon irgendne brauchbare Literatur?

Ja. Data Binding with Windows Forms 2.0

M
5 Beiträge seit 2006
vor 17 Jahren

Ja, habe ich dann auch gefunden. 🙂

Mike Dub (http://www.mikedub.net/) hat eine Klasse ReadOnlySortingBindingList geschrieben, die das Problem schonmal so einigermaßen angeht. Allerdings: ReadOnly und nur für Standardspalten, sprich, diese lustigen DropDown-Spalten gehen nicht so ganz.

Hat jemand eine Klasse, die die Read-Only-Beschränkung nicht aufweist?

Danke, Matthias

347 Beiträge seit 2006
vor 17 Jahren

Ich habe mal eine Lib angehängt, mit der ich in meinem ORM client-seitig Sortierungen durchführe.
Ich bin nicht so der GUI-Experte, habe mich aber dennoch mal getraut damit schnell IBindingListView so zu implementieren, dass man damit durch eine BindingSource sortieren kann.
Die BindingListView-Implementierung kann sicherlich jemand verbessern, aber mit der Lib sind (schnelle!) Sortierungen kein Problem.

namespace RG.Samples.SortableLists
{
    public class SortableBindingList<T> : BindingList<T>, IBindingListView
    {
        ListSortDescriptionCollection sortDescriptions;

        public SortableBindingList()
            : base()
        { }

        public SortableBindingList(IList<T> list)
            : base(list)
        { }

        string orderByClause;
        Comparison<T> comparison;

        #region IBindingListView Members

        void IBindingListView.ApplySort(ListSortDescriptionCollection sorts)
        {
            if (sorts == null || sorts.Count == 0)
            {
                sortDescriptions = null;
                orderByClause = null;
                comparison = null;
            }
            else
            {
                orderByClause = OrderClauseParser.GetOrderByClause(sorts);
                comparison = PropertyComparer<T>.GetMethod(orderByClause);
                Sorter<T>.Sort(this.Items, comparison);
                this.ResetBindings();

                sortDescriptions = sorts;
            }
        }

        string IBindingListView.Filter
        {
            get
            {
                throw new NotImplementedException("The method or operation is not implemented.");
            }
            set
            {
                throw new NotImplementedException("The method or operation is not implemented.");
            }
        }

        void IBindingListView.RemoveFilter()
        {
            throw new NotImplementedException("The method or operation is not implemented.");
        }

        ListSortDescriptionCollection IBindingListView.SortDescriptions
        {
            get { return sortDescriptions; }
        }

        bool IBindingListView.SupportsAdvancedSorting
        {
            get { return true; }
        }

        bool IBindingListView.SupportsFiltering
        {
            get { return true; }
        }

        #endregion
    }
}
M
5 Beiträge seit 2006
vor 17 Jahren

Hallo!

Vielen Dank, ich werde Deinen Code gleich ausprobieren. Warum hat Microsoft nicht soetwas dabeigetan bzw. BindingList<T> sortierfähig gemacht?

Gruß,
Matthias

M
5 Beiträge seit 2006
vor 17 Jahren

Hallo!

Kannst Du vielleicht auch noch den Source Code für die drei Klassen

  • OrderClauseParser
  • PropertyComparer<T>
  • Sorter

posten? (Oder sind die "closed source"?)

Vielen Dank auf jeden Fall schonmal für das bisherige!

Matthias

563 Beiträge seit 2004
vor 17 Jahren

Original von Golo Haas
Insgesamt bin ich von dem DGV ein wenig enttäuscht, das Teil wird angepriesen als die ultimative Lösung für alles mögliche und mit zig tollen neuen Features, und im Kleingedruckten kommt dann wahnsinnig oft der Hinweis, dass es in diesem und jenem Ausnahmefall eben doch nicht ganz so leicht geht ...

Das Problem habeich auch. Ich packe nur ungerne alles immer in ein DataSet. Will man allerdings all die coolen Features wie Filtering, Sorting usw. kommt man aber nicht drum, ausser man implementiert immer alle Interfaces, was einen beträchtlichen Mehraufwand ist. ICh werde mir allerdings nächstens dieser Problematik widmen, mal schauen was sich da machen lässt.

Diese Typed DataSets im Designer sagen mir überhaupt nicht zu. Ich will jede einzelne Zeile programmieren, dann ists auch nachvollziehbar.

http://www.codeproject.com/csharp/customcollection.asp könnte evtl. Interessant sein, habe nur kurz die Übersicht gelesen.

.unreal

M
5 Beiträge seit 2006
vor 17 Jahren

Ich habe folgenden Code hinzugefügt, damit auch die IBindingList sortierbar ist:


        void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction) {
            ListSortDescription[] sda = new ListSortDescription[1];
            sda[0] = new ListSortDescription(property, direction);
            ListSortDescriptionCollection sd = new ListSortDescriptionCollection(sda);
            comparison = PropertyComparer<T>.GetMethod(sd);
            Sorter<T>.Sort(this.Items, comparison);
        }

        bool IBindingList.SupportsSorting
        {
            get { return true; }
        }

Leider sortiert er Daten nicht richtig (sondern als String, kann aber auch an meiner Datenquelle liegen, ich glaube, da ist ein komischer Formatierer drauf). Und es gibt NullReferenceExceptions beim Sortieren von ComboBox-Spalten. Ansonsten klappt es schon ganz gut 😉

Gruß,
Matthias

347 Beiträge seit 2006
vor 17 Jahren

Du solltest für GetMethod einen orderby string nehmen. Dadurch wird immer die gleiche Methode wiederverwendet. Bei deinem Code wird er jedes Mal eine neue Sortiermethode generieren.
Außerdem müssen es tatsächlich Eigenschaften oder Felder von T sein.
Es wird eine Methode generiert, die praktisch dem entspricht was man in einer selbstgeschriebenen Sortiermethode benutzen würde.
Bei Reference types prüft er zuerst auf null, sowohl für das element selbst als auch für die Eigenschaften/Felder.
Weshalb ich mir die NullReferenceEx nicht wirklich erklären kann. 😉
Du kannst auch direkt Sorter<T>.Sort(deineListe, "Eigenschaft1, Eigenschaft2 desc") schreiben oder den OrderString dort rein packen. (Intern wird dann auch pro T und OrderString die gleiche Methode immer wiederverwendet).

btw: Der OrderString ist case sensitive!

347 Beiträge seit 2006
vor 17 Jahren

Original von MatthiasWuttke
Hallo!

Kannst Du vielleicht auch noch den Source Code für die drei Klassen

  • OrderClauseParser
  • PropertyComparer<T>
  • Sorter

posten? (Oder sind die "closed source"?) Die Lib ist ein Ilmerge aus 2 Assemblies, und davon auch nur ein Subset. 😉
Die drei Klassen selbst machen recht wenig selbst, sie verwenden einen ziemlichen Rattenschwanz an anderen Klassen.
Sorter macht nix weiter (in dieser Lib) als zwischen Selection bzw. QuickSort zu wählen (je nach Listgröße).
OrderClauseParser benutzt eine in die Dll kompilierte RegEx um einen SQL-like OrderBy string zu zerlegen. Auch nix wirklich Besonderes.
PropertyComparer hält eine Liste von OrderBy Strings pro T mit der damit verbundenen Sortiermethode.
Wie gesagt, der Rattenschwanz liegt in den Klassen, mit denen du nicht direkt zu tun hast. Die den passenden IL-Code für den Vergleich generieren.

Den Source code möchte ich nicht posten, richtig. Aber solange beim IlMerge oder dem Entfernen anderer Klasen nicht schief ging sollte es eigentlich einwandfrei laufen, du solltest also nichts daran ändern müssen. 😉
Der Sinn davon ist zwar nicht die verkrüppelte Sortansätze von IBindingList aufufüllen, aber solange die Propertydescriptors tatsächliche Eigenschaften oder Felder sind, sollte alles glatt gehen.

Eigentlich sortiere ich damit generische "normale" Container. 😉

Vielen Dank auf jeden Fall schonmal für das bisherige! Kein Problem! 🙂
Falls irgendwas ist kannst mich per PN erreichen, ich schaue hier relativ oft vorbei. Auch wenn ich vllt nicht viel antworte. 😉

347 Beiträge seit 2006
vor 17 Jahren

Original von Robert G

Den Source code möchte ich nicht posten, richtig. Aber solange beim IlMerge oder dem Entfernen anderer Klasen nicht schief ging sollte es eigentlich einwandfrei laufen, du solltest also nichts daran ändern müssen. 😉
Der Sinn davon ist zwar nicht die verkrüppelte Sortansätze von IBindingList aufufüllen, aber solange die Propertydescriptors tatsächliche Eigenschaften oder Felder sind, sollte alles glatt gehen.
Tja, das kommt davon wenn man die Klappe zu weit aufreißt. 😁
Ich hatte die beschnittene Assembly nicht durch ale Test suites gescheucht. Das habe ich heute nachgeholt und musste doch noch ein paar Dinge wieder aufnehmen.

@Matthias
Ich habe diese alte Version damit ersetzt. Wahrscheinlich hast du davon nix davon bemerkt, da die Probleme eigentlich nur auftraten wenn T ein Nullable<T> war oder eine der zu sortierenden Spalten einer war.