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

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

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

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

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

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

  • 項目コンテナーは、ItemsControl に直接追加されます。 たとえば、アプリケーションによって明示的に ListBoxItem オブジェクトが ListBox に追加された場合、ListBox では ListBoxItem オブジェクトが仮想化されません。

  • ItemsControl の項目コンテナーにはさまざまな種類があります。 たとえば、Separator オブジェクトを使用する Menu では項目のリサイクルを実装できません。これは、MenuSeparator および MenuItem という種類のオブジェクトが含まれているためです。

  • CanContentScrollfalse に設定します。

  • IsVirtualizingfalse に設定します。

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

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

コンテナーのリサイクル

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

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

双方向仮想化のサポート

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

テンプレートの最適化

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

遅延スクロール

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

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

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

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

Control 仮想化 コンテナーのリサイクル 遅延スクロール
ComboBox 有効にできます 有効にできます 有効にできます
ContextMenu 有効にできます 有効にできます 有効にできます
DocumentViewer 使用不可 使用できません 有効にできます
ListBox Default 有効にできます 有効にできます
ListView Default 有効にできます 有効にできます
TreeView 有効にできます 有効にできます 有効にできます
ToolBar 使用不可 使用できません 有効にできます

注意

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

関連項目