wpf のデータグリッドの遅さに苦労しています。使用しているコレクション (List、BindingList、ObservableCollection、カスタム ObservableCollection) に関係なく、コレクションの更新 (Clear、Add) に応答して画面にレンダリングすると、依然として非常に遅くなります。
私たちが見つけた最速の解決策は、コレクションを更新するのではなく、DataGrid がバインドされているコレクション内の既存のオブジェクトを更新することです。この場合、古い winforms グリッドのように、グリッドは非常に高速に応答しています。
グリッドに 65535 行を作成していますが、これはすべてのグリッドに十分です。グリッドを更新するときは、必要な数の一番上の行を更新し、残りの行について visibility = hidden を設定します。私が言ったように、それは非常に速く動作します。しかし、解決できない問題が 2 つあります。
- 行を折りたたまない (遅い) ため、スクロール バーは常に 65535 行に設定されます。スクロールまたはグリッド サイズを実際に表示される行数に制限する方法はありますか?
また、すぐにレンダリングする必要がない場合 (可視領域外になる)、新しい行をコレクションに追加することも非常に高速であるため、最小セットを 50 行 (最大可視) に制限できることに気付きました。行)、必要に応じて新しい行を追加/削除します。しかし、これはスクロールの問題を解決しません。
他のソリューションは大歓迎です。仮想化を有効にするようにというアドバイスの予見-はい、仮想化を使用しています(デフォルトで有効になっている行と列に対して)。
更新: 20 列 x 50 行のデータを表示しようとしています。Clear() と Add() を使用してソース コレクションを変更すると、レンダリング時間は約 1 秒になり、UI が 1 秒間フリーズするため、これはまったく許容できません。データグリッドのサイズを 0 の高さに変更しようとした後、バックグラウンド スレッドで段階的にサイズを元に戻すと、UI のフリーズが解除されますが、見落としが見苦しく、親コントロールを埋めるためにデータグリッドを元に戻す方法を管理できませんでした。コードで Height を設定した後は、元に戻せないようです。最初の投稿と同様に、コレクションを変更しないという別の解決策が見つかりました。グリッドを 65535 行に制限するだけで、新しい項目を追加または削除しないでください。これは非常に高速に動作しますが、現在、スクロールとソートの同期で問題に直面しています。
データグリッドは WPF で非常にイライラするコントロールであることがわかりました。パフォーマンスは合理的な制限を下回っています。私たちが達成しようとしているのは応答性です。データをロードするとき、UI を数ミリ秒以上ブロックしないでください。
XAML: 特別なことは何もありません
<DataGrid x:Name="TheGrid"
DockPanel.Dock="Top"
ItemsSource="{Binding Collection}"
EnableColumnVirtualization="True"
EnableRowVirtualization="True"
AutoGenerateColumns="False"
ColumnWidth="70"
RowHeight="20"
>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Header 1" >
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding Field1, Mode=TwoWay}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Field1}" /></DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn >
..... 20列の場合など
また、データグリッドは StackPanel 内にありません (これにより、非常に遅くなります)。