2009-05-12 9 views
22

私は非常に多くのデータ(10000〜100000)行のリストビューを含むwpfアプリケーションで作業しています。ユーザーはこのリストビューにあらゆる種類のフィルターを適用することができます。フィルターロジックはかなり高度な(そして遅い)ものになります。大きなデータセットを持つWPFのICollectionView.filter

ICollectionView view = CollectionViewSource.GetDefaultView(hugeList.ItemsSource); 
view.Filter = new Predicate<object>(FilterCallback); 

private bool FilterCallback(object item) 
{ 
    //Filter logic 
} 

をしかし、これは、アプリケーション全体をUIスレッドで実行され、ブロック時に非常に悪いユーザー体験を提供するフィルタリング:今のところ、私のコードの関連部分はこのようになります。ですから、私の質問はすべてです:wpfでリストビューをフィルタリングするための「より良い」方法を知っている人や、基礎となるObservableCollectionをフィルタする必要がありますか?

+0

+1いい質問です!あなたはどのような解決策を打ち出しましたか? – gehho

+0

パフォーマンス上の問題は、グリッドバインディング/レンダリング側のもので、実際のフィルタロジックには関連しない可能性があります。 – Schneider

答えて

20

フィルタ機能には十分注意してください。あなたが不必要なボクシング/アンボクシングをしていないことを確認し、あなたはそれで広範な計算を行っていません。使用しているCollectionViewの種類に注意を払う必要があります。いくつかは他のものより高速です。 Bea's post on sortingから:あなたのソースはIEnumerableを実装している場合

  • CollectionViewが作成されます。ソースがIEnumerable を実装している場合は、のみをソートまたはグループ化することはできません(フィルタリングのみできます)。また、ソースに多数の項目がある場合、または挿入や削除などの動的操作を実行する場合は、perfは最適ではありません。これがあなたのシナリオである場合、あなたのソースがより強力なインターフェースを実装することを考慮する必要があります。 ICollectionは、Countプロパティを提供するため、若干優れています。

  • ListCollectionViewは、ソースがIListを実装するときに作成されるビュータイプです。 IEnumerableやICollectionと比較して、IListはインデクサーを提供するため、大規模または動的リストの方がはるかに優れているため、迅速なランダムアクセスが可能です。さらに、IListではソート、グループ化、およびフィルタリングが可能です。しかし、理想的には、ソースコレクションは、プロパティとコレクションの変更通知などのいくつかの追加機能を提供するため、すべてのコレクションの母親であるObservableCollectionから派生しています。

  • BindingListCollectionViewは、ソースコレクションがIBindingListを実装するときにAvalonによって作成されるビューのタイプです。これは、ADO.NETシナリオで扱うビューです。ソートやグループ化はサポートしていますが、従来のフィルタリングはサポートしていません。代わりに、DataViewにフィルタリングを委譲する追加のCustomFilterプロパティがあります(詳細はADO.NETの投稿を参照してください)。

@mihiは言ったが、私は〜60個の変数(データベーステーブルの列)を対象に50,000アイテムでのObservableCollection上で同時に複数のフィルタを実行するためにCollectionViewsを使用していたとしてあなたは別のスレッドにフィルタリングを蹴ることができます顕著な遅れなしに。

あなたのフィルタ関数で直ちに気づくのは、入力がObject型であるということです。これは、関数内で型変換を行っている可能性があります。また、戻り値の型を含まないPredicateを使用すると、おそらくCollectionViewのフィルタリングメソッド内で型変換やリフレクションが必要になり、遅くなることもあります。

+2

フィルタを別のスレッドに移動する方法を示すサンプルコードを追加してください。私はこれを別のスレッドで動作させるように見えることはできません。 – Luke

+5

@Bryan:同様の状況があり、フィルタのパフォーマンスを向上させたいと考えています。答えには、「述語」を使用しないでください。なぜなら、ボクシング/アンボクシング操作が必要であり、戻り値の型が含まれていないからです。それはどういう意味ですか?戻り値の型は 'bool'です。' ListCollectionView'の 'Filter'プロパティはそのように定義されているため、' Predicate 'でなければなりません。これを回避し、別のフィルター手法を使用する方法はありますか?あなたの意図は何でしたか?たぶん私はちょうどそれを誤解した... – gehho

+0

@gehho私は減速を引き起こす可能性があるもののための時間のアイデアを投げていたと思う。 100回のうち99回は、問題の原因となっているフィルタリングロジックが遅くなることがあります。 –

3

他のスレッドでディスパッチしたり、ディスパッチャーを使用していましたか?

WPF Threads: Build more responsive apps with the dispatcherは、利用可能なスレッドオプションの概要を示しています。

+1

私はこれを考慮しましたが、私はこれとは別のスレッドで 'ICollectionView'にアクセスできませんUIスレッド? –

+2

いいえ、Dispatcher.Invokeを使用して別のスレッドでフィルタリングロジックを実行し、UIスレッドのコレクションを変更することができます –

+1

このソリューションの良い例は次のとおりです。http://www.codeproject.com/Articles/32426/Deferring- ListCollectionView-filter-updates-for- –