パフォーマンスの最適化 : コントロール

更新 : 2008 年 7 月

Windows Presentation Foundation (WPF) には、大半の Windows アプリケーションで使用される一般的なユーザー インターフェイス (UI) コンポーネントが多数含まれています。このトピックでは、UI のパフォーマンスを向上させる方法について説明します。

このトピックには次のセクションが含まれています。

  • 大容量のデータ セットの表示
  • コンテナのリサイクル
  • 双方向仮想化のサポート
  • テンプレートの最適化
  • 遅延スクロール
  • パフォーマンス機能を実装するコントロール
  • 関連トピック

大容量のデータ セットの表示

アプリケーションで項目リストを表示するには、ListViewComboBox などの WPF コントロールが使用されます。表示するリストが大きい場合、アプリケーションのパフォーマンスに影響する可能性があります。これは、標準的なレイアウト システムでは、リスト コントロールに関連付けられた項目ごとにレイアウト コンテナを作成した後、コンテナのレイアウト サイズと位置を計算するためです。通常、すべての項目を同時に表示する必要はありません。その代わりに項目のサブセットが表示され、ユーザーはリストをスクロールすることで、すべての項目を確認します。このような場合は、UI の仮想化が役に立ちます。これは、項目に対する項目コンテナの生成と関連するレイアウトの計算を、項目が表示されるまで遅らせることを意味します。

UI の仮想化は、リスト コントロールにとって重要な処理です。UI の仮想化とデータの仮想化を混同しないでください。UI の仮想化では、表示される項目だけをメモリに格納しますが、データのバインディングがある場合はデータ構造体のすべてがメモリに格納されます。これに対し、データの仮想化では、画面上に表示されているデータ項目だけがメモリに格納されます。

既定では、UI の仮想化は、ListView コントロールと ListBox コントロールで、それぞれのリスト項目がデータにバインドされる場合は有効になっています。TreeView の仮想化は、VirtualizingStackPanel.IsVirtualizing 添付プロパティを true に設定することで有効にできます。ItemsControl から派生するカスタム コントロール、または StackPanel クラスを使用する既存のコントロール (ComboBox など) で UI の仮想化を有効にする場合は、ItemsPanelVirtualizingStackPanel に設定し、IsVirtualizing をtrue に設定します。ただし、これらのコントロールに対する UI の仮想化は、仮想化を実現せずに無効にできます。UI の仮想化を無効にする条件を一覧で示します。

現時点では、データの仮想化のサポートが組み込まれている WPF コントロールはありません。

コンテナのリサイクル

.NET Framework 3.5 SP1 で、ItemsControl から継承するコントロール用として追加された UI の仮想化に対する最適化はコンテナのリサイクルです。コンテナのリサイクルによってスクロールのパフォーマンスも向上します。UI の仮想化を使用する ItemsControl が設定されると、項目をスクロールして表示するたびに項目コンテナが作成され、項目をスクロールして非表示にするたびに項目コンテナが破棄されます。コンテナのリサイクルでは、異なるデータ項目用の既存の項目コンテナをコントロールが再利用できるので、ユーザーが ItemsControl をスクロールするたびに項目コンテナの作成と破棄が常に行われることはありません。VirtualizationModeRecycling に設定することで、項目のリサイクルを有効にすることを選択できます。

コンテナのリサイクルは、次のいずれかの状況に該当する場合は使用されません。

  • 項目コンテナが ItemsControl に直接的に追加される。たとえば、ListBoxItem オブジェクトは、ListBox コントロールに直接的に追加されます。項目コンテナの詳細については、「Control コンテンツ モデルの概要」の ItemsControl の項を参照してください。

  • ItemsControl に含まれる項目コンテナの種類が異なる。たとえば、Separator オブジェクトを使用する Menu では、項目のリサイクルを実装できません。これは、Menu には、Separator 型のオブジェクトと MenuItem 型のオブジェクトが含まれるからです。

項目コンテナをリサイクルする際の重要な考慮事項は、項目に関係する項目コンテナに関連付けられた追加の状態情報の有無です。その場合は、追加状態を保存する必要があります。たとえば、Expander コントロールに含まれる項目で、IsExpanded 状態が、項目自体ではなく、項目コンテナにバインドされている場合があります。このコンテナが新しい項目に対して再利用される場合、新しい項目には IsExpanded の現在の値が使用されます。さらに、古い項目は、正しい IsExpanded 値を失います。

仮想化をサポートするすべての ItemsControl で、コンテナのリサイクルを使用できます。ListBox でコンテナのリサイクルを有効にする方法の例については、「方法 : ListBox のスクロール速度を向上させる」を参照してください。

双方向仮想化のサポート

VirtualizingStackPanel には、水平または垂直のいずれかの方向での UI の仮想化のサポートが組み込まれています。コントロールに対して双方向の仮想化を使用する場合は、VirtualizingStackPanel クラスを拡張するカスタム パネルを実装する必要があります。VirtualizingStackPanel クラスは、OnViewportSizeChangedLineUpPageUpMouseWheelUp などの仮想メソッドを公開します。これらの仮想メソッドを使用して、リストの表示部分の変更を検出し、変更に応じた処理を実行できます。

テンプレートの最適化

ビジュアル ツリーには、アプリケーションのすべてのビジュアル要素が含まれます。直接的に作成されたオブジェクトに加え、テンプレートの拡張によって追加されたオブジェクトも含まれます。たとえば、Button を作成すると、ビジュアル ツリーには、ClassicBorderDecorator オブジェクトと ContentPresenter オブジェクトも取得されます。コントロール テンプレートを最適化していない場合、必要のない余分なオブジェクトがビジュアル ツリーの中に多数作成される可能性があります。XAMLPad を使用してビジュアル ツリー内の要素を追跡し、必要に応じてテンプレート内の不要な項目を削除できます。ビジュアル ツリーの詳細については、「Windows Presentation Foundation のグラフィックス レンダリングの概要」を参照してください。

遅延スクロール

既定では、ユーザーがスクロールバーのつまみをドラッグすると、コンテンツ ビューが連続的に更新されます。コントロールのスクロールが遅い場合は、遅延スクロールの使用を検討してください。遅延スクロールでは、コンテンツは、ユーザーがつまみを離したときにのみ更新されます。

遅延スクロールを実装するには、IsDeferredScrollingEnabled プロパティを true に設定します。IsDeferredScrollingEnabled は添付プロパティであり、ScrollViewer と、コントロール テンプレート内に ScrollViewer が含まれているすべてのコントロールに設定できます。

パフォーマンス機能を実装するコントロール

次の表は、データを表示するための一般的なコントロールと、各コントロールのパフォーマンス機能に対するサポートを示しています。これらの機能を有効にする方法については、前のセクションを参照してください。

コントロール

仮想化

コンテナのリサイクル

遅延スクロール

ComboBox

有効にできます。

有効にできます。

有効にできます。

ContextMenu

有効にできます。

有効にできます。

有効にできます。

DocumentViewer

使用できません。

使用できません。

有効にできます。

ListBox

既定値です。

有効にできます。

有効にできます。

ListView

既定値です。

有効にできます。

有効にできます。

TreeView

有効にできます。

有効にできます。

有効にできます。

ToolBar

使用できません。

使用できません。

有効にできます。

メモ :

TreeView に対する仮想化とコンテナのリサイクルを有効にする方法の例については、「方法 : TreeView のパフォーマンスを改善する」を参照してください。

参照

概念

レイアウト システム

パフォーマンスの最適化 : レイアウトとデザイン

パフォーマンスの最適化 : データ バインディング

コントロールの概要

スタイルとテンプレート

履歴の変更

日付

履歴

理由

2008 年 7 月

.NET Framework 3.5 Service Pack 1 のトピックを追加

SP1 機能変更