CodePlexと、Bea Stollnitzのブログと Vincent Da Ven Berhge の論文 (同じリンク)からのいくつかのアイデアを使用して、データ仮想化ソリューションを実装しました。ただし、別のアプローチが必要だったので、独自のソリューションを作成することにしました。
DataGrid
このソリューションで約100万行を表示するために使用しています。UI仮想化も使用しています。DataGrid
私の解決策は実行可能ですが、特定の状況でソースからデータを要求する方法に関する奇妙な動作が発生します。
解決策について
私はすべての重い仕事をするリストを書くことになりました。It という名前の汎用クラスでありVirtualList<T>.
、インターフェイスを実装しているICollectionViewFactory
ため、コレクション ビュー作成メカニズムはVirtualListCollectionView<T>
それをラップするインスタンスを作成できます。このクラスは から継承されListCollectionView
ます。私は提案に従って、独自のICollectionView
実装を作成しませんでした。継承もうまくいくようです。
はVirtualList<T>
、データ全体をページに分割します。項目の合計数を取得し、リスト インデクサーを介して行を要求するたびにDataGrid
、適切なページを読み込むか、キャッシュから返します。ページは内部でリサイクルされ、DispatcherTimer
未使用のページはアイドル時間に破棄されます。
データ リクエストのパターン
私が最初に学んだことは、
VirtualList<T>
実装する必要がありますIList
(一般的ではありません)。それ以外の場合、ItemsControl
はそれを として扱い、IEnumerable
すべての行をクエリ/列挙します。DataGrid
はタイプセーフではないため、これは論理的であり、IList<T>
インターフェイスを使用できません。インデックスが 0 の行は、 から頻繁に尋ねられます
DataGrid
。ビジュアルアイテムの計測に使われているようです(コールスタックによると)。したがって、これをキャッシュするだけです。内部のキャッシング メカニズム
DataGrid
は、予測可能なパターンを使用して、表示される行をクエリします。最初に、上から下に表示されている行を要求し (行ごとに 2 回)、次に、表示されている領域 (最初の表示されている行を含む) の前にあるいくつかの行 (表示されている領域のサイズに応じて) を降順でクエリします。下から上に並べます。その後、表示されている行 (最後に表示されている行を含む) の後、上から下まで同じ量の行を要求します。表示される行インデックスが 4,5,6 の場合。データ要求は次のようになります: 4,4,5,5,6,6,4,3,2,1,6,7,8,9.
ページ サイズが適切に設定されていれば、現在および以前に読み込まれたページからこれらすべてのリクエストを処理できます。
CanSelectMultipleItems
でTrue
あり、ユーザーが SHIFT ボタンまたはマウス ドラッグを使用して複数の項目を選択するとDataGrid
、リストの先頭から選択範囲の末尾までのすべての行が列挙されます。この列挙は、実装されIEnumerable
ているかどうかに関係なく、インターフェイスを介して行われます。IList
選択された行が表示されず、現在の表示領域が選択された行から「遠い」場合、選択された行から表示領域の最後まで、DataGrid がすべての項目の要求を開始することがあります。間にあるすべての行を含めて、表示さえされていません。この動作の正確なパターンを理解できませんでした。たぶん私の実装がその理由です。
私の質問
DataGrid
非表示の行が表示されると再度要求されるので、なぜ非表示の行を要求するのですか?すべての行を 2 回または 3 回要求する必要があるのはなぜですか?
IEnumerable
複数の項目の選択をオフにする以外に、DataGrid を使用しないようにする方法を教えてもらえますか?