1

wpf のデータグリッドの遅さに苦労しています。使用しているコレクション (List、BindingList、ObservableCollection、カスタム ObservableCollection) に関係なく、コレクションの更新 (Clear、Add) に応答して画面にレンダリングすると、依然として非常に遅くなります。

私たちが見つけた最速の解決策は、コレクションを更新するのではなく、DataGrid がバインドされているコレクション内の既存のオブジェクトを更新することです。この場合、古い winforms グリッドのように、グリッドは非常に高速に応答しています。

グリッドに 65535 行を作成していますが、これはすべてのグリッドに十分です。グリッドを更新するときは、必要な数の一番上の行を更新し、残りの行について visibility = hidden を設定します。私が言ったように、それは非常に速く動作します。しかし、解決できない問題が 2 つあります。

  1. 行を折りたたまない (遅い) ため、スクロール バーは常に 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 内にありません (これにより、非常に遅くなります)。

4

3 に答える 3

1

最後に、ハッキングしすぎない任意の数の行にスクロールを制限する方法を見つけました。ScrollView で行数を取得するために使用される ICollection を実装するバインディング用の独自のリストを作成しました。Measure を呼び出す前に設定した表示行数を返すように ICollection.Count を変更してから、実際の行数に戻します。それはうまく機能し、スクロールに関するすべての問題を解決しました. したがって、静的な行数を持つリストにバインドされたグリッドがあり、表示したい最初の n 行に visibility=Visible を設定します。 、スクロールを表示可能な行に制限します。リストにあるオブジェクトは、さまざまなスレッドから更新できます。WPF 自体が行うため、Dispatcher を呼び出す必要はありません。

于 2012-11-18T13:04:42.840 に答える
0

それでも同じ時間がかかるので、それは正しい解決策ではないかもしれないことを私は知っています。ただし、マルチスレッド化すると、フリーズの問題が解決します。次に、バックグラウンドのグリッドにデータを入力して、実行時に1つずつ追加するか、終了時にすべて追加することができます。

于 2012-11-11T08:38:59.933 に答える
0

あなたに役立つかもしれないページを見つけました。

1 つ目は、データグリッドに値をキャッシュすることです: http://msdn.microsoft.com/en-us/library/system.windows.uielement.cachemode(v=vs.100).aspx

2 つ目は、データグリッドの仮想モードの実装に関するものです: http://msdn.microsoft.com/en-us/library/15a31akc.aspx

お役に立てば幸いです

更新: スクロール ビューを使用していますか? あなたがそうであるなら、それは目に見えるものだけではなく、すべての行をロードするからです。この質問への回答を参照してみてください: How to lazy-evaluate a wpf:DataGrid, retrieves only as needed as the data

于 2012-11-08T16:16:43.390 に答える