Frage

Ich habe eine ObservableCollection von Viewmodels, die in einer WPF DataGrid sitzen. Die DataGrid hat drei Spalten:

  • Spalte Position; dies wird zur Laufzeit von einem Usercontrol gemacht, die die Position der Zeile in meinem Datagrid
  • zeigen
  • Name Spalte; dies wird zur Laufzeit von einem Usercontrol gemacht, die den Namen der Spalte zeigt (ja, ich brauche einen Usercontrol dafür auf, wie der Name angezeigt werden muss, aber das ist eine Seite)
  • Datenspalte; dies wird zur Laufzeit von noch einem anderen Usercontrol erstellt.

sind meine Spalten wie folgt definiert:

        <toolkit:DataGrid.Columns>
            <toolkit:DataGridTemplateColumn Header="" MinWidth="35" MaxWidth="35" SortMemberPath="Position.PositionIndex" CanUserSort="True">
                <toolkit:DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ContentPresenter Content="{Binding Path=Position}"/>
                    </DataTemplate>
                </toolkit:DataGridTemplateColumn.CellTemplate>
            </toolkit:DataGridTemplateColumn>
            <toolkit:DataGridTemplateColumn Header="Name" MinWidth="150" Width="150" SortMemberPath="Name" CanUserSort="True">
                <toolkit:DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ContentPresenter Content="{Binding Path=Name}"/>
                    </DataTemplate>
                </toolkit:DataGridTemplateColumn.CellTemplate>
            </toolkit:DataGridTemplateColumn>
            <toolkit:DataGridTemplateColumn Header="Data" Width="Auto" CanUserSort="False">
                <toolkit:DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ContentPresenter Content="{Binding Path=Data}"/>
                    </DataTemplate>
                </toolkit:DataGridTemplateColumn.CellTemplate>
            </toolkit:DataGridTemplateColumn>
        </toolkit:DataGrid.Columns>

Also, weil meine Row und Name Spalte sind Benutzersteuerelemente, die WPF DataGrid kann nicht native Art auf sich. So erleichtert das Sortieren, wenn eine Spaltenüberschrift geklickt wird, kann ich einige ListCollectionView.CustomSort Magie.

Hier ist, was mein benutzerdefinierter Sortierer aussieht für den Spalt Namen:

// Customized sorter, by name, ascending.
public class AscendingNameSorter : IComparer
{
    public int Compare(object x, object y)
    {
        var lhs = (MyViewModel)x;
        var rhs = (MyViewModel)y;

        return lhs.Name.CompareTo(rhs.Name);
    }
}

// Customized sorter, by name, descending.
public class DescendingNameSorter : IComparer
{
    public int Compare(object x, object y)
    {
        var lhs = (MyViewModel)x;
        var rhs = (MyViewModel)y;

        return rhs.Name.CompareTo(lhs.Name);
    }
}

Das Problem ist, dass dies unglaublich langsam . Ich kann nicht herausfinden, warum. Mit 10 Elementen in den DataGrid, mahlt meine Anwendung zum Stillstand für 3-4 Sekunden, während es zurückgreift. Ich dachte, ListCollectionView.CustomSort sollte der effizienteste Weg, um eine ObservableCollection zu sortieren ... wo soll ich denn falsch?

War es hilfreich?

Lösung

WPF wird alle Ihre Benutzersteuerelemente jedes Mal die Art Änderungen neu zu erstellen, so meine Vermutung ist, dass etwas in der Konstruktion dieser Kontrollen langsam ist. Aber das ist nur eine Vermutung.

Sie sollten durch Eingrenzung des Problems beginnen. Hier sind einige Schritte Sie ergreifen können:

  1. Finden Sie heraus, die den Betrieb 3-4 Sekunden stattfindet. Sie haben nicht feststellen, ob die Verzögerung geschieht nur, wenn Sie den Wert auf CustomSort zuweisen oder jedesmal, wenn die Liste ändert sich nach CustomSort gesetzt wurde. Das macht einen Unterschied.

  2. Versuchen Sie, eine normale Textspalte hinzufügen und Sortierung auf den Einbau-Art, um zu sehen, ob es schnell ist oder nicht. Vielleicht haben Sie dies bereits getan, aber du hast nicht in Ihrer Frage sagen.

  3. Für diagnostische Zwecke vorübergehend einstellen CustomSort stoppen und stattdessen ListCollectionView.Filter gesetzt. Setzen Sie sich auf einen Filter, der immer true zurück. Wenn Sie immer noch die Verlangsamung bekommen, ist das Problem auf Listcollectionview Versuch verwandte Elemente neu zu organisieren.

  4. Zur Zeit Vorlagen bearbeiten und individuelle Benutzersteuerelemente mit etwas trivial (zB <CheckBox/>) ersetzen, um zu sehen, ob die Dinge zu beschleunigen oder nicht.

  5. Setzen Sie Haltepunkte in der Konstrukteurs Ihres Benutzersteuerelemente, um zu sehen, ob sie die erwartete Anzahl der Male aufgerufen werden (dh 10 Konstruktor ruft, wenn es 10 Elemente in der Liste sind). Wenn sie mehr Zeit als erwartet genannt werden, auf dem Stapel sehen Spuren zu sehen, wo die zusätzlichen Anrufe kommen aus.

  6. Fügen Sie Code zu Ihrer Usercontrol Konstrukteure die DateTime.Now die Konstrukteure in das Ausgabefenster (oder einem Protokoll, oder was auch immer) genannt wurden zu schreiben. Dies gibt Ihnen eine Vorstellung, wie lange jeder nimmt.

  7. Fügen Sie mehrere hundert Artikel zu Ihrem ObservableCollection, führen Sie Ihre Anwendung Seite an Seite mit VS.NET, klicken Sie auf Ihre Art Button (oder was auch immer), dann drücken Sie die Pause Schaltfläche Alles in VS.NET und Blick auf die Stack-Trace. Hit Weiter und Hit sofort Break alle wieder, dann schauen Sie auf dem Stack-Trace wieder. Wiederholen Sie viele Male. Dies gibt Ihnen eine gute Vorstellung davon, was all die zusätzliche Zeit nimmt.

Wenn man, wie ich vermute, das Problem langsam Benutzersteuerelemente Erstellung und Bindung, werden Sie feststellen: Das Problem bei jeder Liste Veränderung passiert und passiert auch, wenn Sie die Filter ändern, die Dinge zu beschleunigen, wenn Sie Ihr Benutzersteuerelement mit <CheckBox/> ersetzen, Ihrem Konstruktor wird nur einmal pro Artikel genannt werden, die Zeit zwischen den Anrufen largish sein wird.

Beachten Sie, dass ich sage nicht, es der Konstruktor der Benutzersteuerelemente, die langsam ist - es könnte sein, dass das Usercontrol viele Unterobjekte instanziiert, wenn er Daten gebunden ist, oder daß sie Objekte, die langsam oder komplex sind, lädt ein Subobjekt eine Datei oder viele andere mögliche Ursachen. Unterm Strich ist, dass auf dem Objekt der Datatemplate instanziieren und an der visuellen Struktur Zugabe etwas langsam tut. Die Stack-Traces sollten Sie eine Idee geben, wo sie suchen müssen.

Sollte es sich um etwas anderes zu sein, oder man kann es nicht herausfinden, nur aktualisieren Sie Ihre Frage mehr Informationen zu geben, was die oben genannten Tests ergaben, und wir werden versuchen, Ihnen zu helfen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top