パフォーマンスの最適化 : コントロール
Windows Presentation Foundation (WPF) には、大半の Windows アプリケーションで使用される一般的なユーザー インターフェイス (UI: User Interface) コンポーネントが多数含まれています。 このトピックでは、UI のパフォーマンスを向上させる方法について説明します。
このトピックは、次のセクションで構成されています。
- 大容量のデータ セットの表示
- コンテナーのリサイクル
- 双方向仮想化のサポート
- テンプレートの最適化
- 遅延スクロール
- パフォーマンス機能を実装するコントロール
- 関連トピック
大容量のデータ セットの表示
アプリケーションで項目リストを表示するには、ListView や ComboBox などの WPF コントロールが使用されます。 表示するリストが大きい場合、アプリケーションのパフォーマンスに影響する可能性があります。 これは、標準的なレイアウト システムでは、リスト コントロールに関連付けられた項目ごとにレイアウト コンテナーを作成した後、コンテナーのレイアウト サイズと位置を計算するためです。 通常、すべての項目を同時に表示する必要はありません。その代わりに項目のサブセットが表示され、ユーザーはリストをスクロールすることで、すべての項目を確認します。 このような場合は、UI の仮想化が役に立ちます。これは、項目に対する項目コンテナーの生成と関連するレイアウトの計算を、項目が表示されるまで遅らせることを意味します。
UI の仮想化は、リスト コントロールにとって重要な処理です。 UI の仮想化とデータの仮想化を混同しないでください。 UI の仮想化では、表示される項目だけをメモリに格納しますが、データのバインディングがある場合はデータ構造体のすべてがメモリに格納されます。 これに対し、データの仮想化では、画面上に表示されているデータ項目だけがメモリに格納されます。
既定では、UI の仮想化は、ListView コントロールと ListBox コントロールで、それぞれのリスト項目がデータにバインドされる場合は有効になっています。 TreeView の仮想化は、VirtualizingStackPanel.IsVirtualizing 添付プロパティを true に設定することで有効にできます。 ItemsControl から派生するカスタム コントロール、または StackPanel クラスを使用する既存のコントロール (ComboBox など) で UI の仮想化を有効にする場合は、ItemsPanel を VirtualizingStackPanel に設定し、IsVirtualizing をtrue に設定します。 ただし、これらのコントロールに対する UI の仮想化は、仮想化を実現せずに無効にできます。 UI の仮想化を無効にする条件を一覧で示します。
項目コンテナーが ItemsControl に直接的に追加される。 たとえば、アプリケーションで ListBoxItem オブジェクトが ListBox に明示的に追加される場合、ListBox は ListBoxItem オブジェクトを仮想化しません。
CanContentScroll を false に設定する。
IsVirtualizing を false に設定する。
項目のグループ化を使用する。
現時点では、データの仮想化のサポートが組み込まれている WPF コントロールはありません。
コンテナーのリサイクル
.NET Framework 3.5 SP1 で、ItemsControl から継承するコントロール用として追加された UI の仮想化に対する最適化はコンテナーのリサイクルです。コンテナーのリサイクルによってスクロールのパフォーマンスも向上します。 UI の仮想化を使用する ItemsControl が設定されると、項目をスクロールして表示するたびに項目コンテナーが作成され、項目をスクロールして非表示にするたびに項目コンテナーが破棄されます。 コンテナーのリサイクルでは、異なるデータ項目用の既存の項目コンテナーをコントロールが再利用できるので、ユーザーが ItemsControl をスクロールするたびに項目コンテナーの作成と破棄が常に行われることはありません。 VirtualizationMode をRecycling に設定することで、項目のリサイクルを有効にすることを選択できます。
コンテナーのリサイクルは、次のいずれかの状況に該当する場合は使用されません。
項目コンテナーが ItemsControl に直接的に追加される。 たとえば、ListBoxItem オブジェクトは、ListBox コントロールに直接的に追加されます。
ItemsControl に含まれる項目コンテナーの種類が異なる。 たとえば、Separator オブジェクトを使用する Menu では、項目のリサイクルを実装できません。これは、Menu には、Separator 型のオブジェクトと MenuItem 型のオブジェクトが含まれるからです。
項目コンテナーをリサイクルする際の重要な考慮事項は、項目に関係する項目コンテナーに関連付けられた追加の状態情報の有無です。 その場合は、追加状態を保存する必要があります。 たとえば、Expander コントロールに含まれる項目で、IsExpanded 状態が、項目自体ではなく、項目コンテナーにバインドされている場合があります。 このコンテナーが新しい項目に対して再利用される場合、新しい項目には IsExpanded の現在の値が使用されます。 さらに、古い項目は、正しい IsExpanded 値を失います。
仮想化をサポートするすべての ItemsControl で、コンテナーのリサイクルを使用できます。 ListBox でコンテナーのリサイクルを有効にする方法の例については、「方法 : ListBox のスクロール速度を向上させる」を参照してください。
双方向仮想化のサポート
VirtualizingStackPanel には、水平または垂直のいずれかの方向での UI の仮想化のサポートが組み込まれています。 コントロールに対して双方向の仮想化を使用する場合は、VirtualizingStackPanel クラスを拡張するカスタム パネルを実装する必要があります。 VirtualizingStackPanel クラスは、OnViewportSizeChanged、LineUp、PageUp、MouseWheelUp などの仮想メソッドを公開します。これらの仮想メソッドを使用して、リストの表示部分の変更を検出し、変更に応じた処理を実行できます。
テンプレートの最適化
ビジュアル ツリーには、アプリケーションのすべてのビジュアル要素が含まれます。 直接的に作成されたオブジェクトに加え、テンプレートの拡張によって追加されたオブジェクトも含まれます。 たとえば、Button を作成すると、ビジュアル ツリーには、ClassicBorderDecorator オブジェクトと ContentPresenter オブジェクトも取得されます。 コントロール テンプレートを最適化していない場合、必要のない余分なオブジェクトがビジュアル ツリーの中に多数作成される可能性があります。 ビジュアル ツリーの詳細については、「WPF グラフィックス レンダリングの概要」を参照してください。
遅延スクロール
既定では、ユーザーがスクロールバーのつまみをドラッグすると、コンテンツ ビューが連続的に更新されます。 コントロールのスクロールが遅い場合は、遅延スクロールの使用を検討してください。 遅延スクロールでは、コンテンツは、ユーザーがつまみを離したときにのみ更新されます。
遅延スクロールを実装するには、IsDeferredScrollingEnabled プロパティを true に設定します。 IsDeferredScrollingEnabled は添付プロパティであり、ScrollViewer と、コントロール テンプレート内に ScrollViewer が含まれているすべてのコントロールに設定できます。
パフォーマンス機能を実装するコントロール
次の表は、データを表示するための一般的なコントロールと、各コントロールのパフォーマンス機能に対するサポートを示しています。 これらの機能を有効にする方法については、前のセクションを参照してください。
コントロール |
仮想化 |
コンテナーのリサイクル |
遅延スクロール |
---|---|---|---|
有効にできます。 |
有効にできます。 |
有効にできます。 |
|
有効にできます。 |
有効にできます。 |
有効にできます。 |
|
使用できません。 |
使用できません。 |
有効にできます。 |
|
既定の設定です。 |
有効にできます。 |
有効にできます。 |
|
既定の設定です。 |
有効にできます。 |
有効にできます。 |
|
有効にできます。 |
有効にできます。 |
有効にできます。 |
|
使用できません。 |
使用できません。 |
有効にできます。 |
メモ |
---|
TreeView に対する仮想化とコンテナーのリサイクルを有効にする方法の例については、「方法 : TreeView のパフォーマンスを改善する」を参照してください。 |