Share via


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

WPF アプリケーションの設計によっては、レイアウトの計算やオブジェクト参照の検証で不要なオーバーヘッドが発生して、パフォーマンスに影響が及ぶことがあります。 オブジェクトの作成 (特に起動時の作成) はアプリケーションのパフォーマンス特性に影響する可能性があります。

このトピックでは、このようなパフォーマンスに関する推奨事項について説明します。

[レイアウト]

"レイアウト パス" という用語は、Panel 派生オブジェクトの子のコレクションのメンバーを測定および配置して、それらを画面上に描画するプロセスを表します。 レイアウト パスは数学的に増大するプロセスで、コレクション内の子の数が多くなれば、必要な計算の数も多くなります。 たとえば、コレクション内の子 UIElement オブジェクトがその位置を変更するたびに、レイアウト システムによる新しいパスがトリガーされる可能性があります。 オブジェクトの特性とレイアウトの動作の間には密接な関係があるため、レイアウト システムを呼び出すことができるイベントの種類を把握することが重要です。 レイアウト パスの不要な呼び出しをできるだけ減らすことで、アプリケーションのパフォーマンスを向上させることができます。

レイアウト システムは、コレクションの子メンバーごとに、測定パスと配置パスという 2 つのパスを実行します。 各子オブジェクトは、それぞれ固有のレイアウト動作を提供するために、Measure メソッドと Arrange メソッドの独自のオーバーライドされた実装を提供します。 簡単に言うと、レイアウトは、要素のサイズ測定、配置、および画面上への描画を繰り返す再帰的なシステムです。

  • UIElement オブジェクトは、最初にそのコア プロパティを測定して、レイアウト プロセスを開始します。

  • オブジェクトのサイズに関連する FrameworkElement プロパティ (WidthHeightMargin など) が評価されます。

  • DockPanelDock プロパティや StackPanelOrientation プロパティなど、Panel 固有のロジックが適用されます。

  • すべての子オブジェクトが測定された後、コンテンツが配置されます。

  • 子オブジェクトのコレクションが画面に描画されます。

以下のアクションが発生すると、再びレイアウト パス プロセスが呼び出されます。

  • 子オブジェクトがコレクションに追加された場合。

  • 子オブジェクトに LayoutTransform が適用された場合。

  • 子オブジェクトに対して UpdateLayout メソッドが呼び出された場合。

  • 測定パスや配置パスに影響を与えるものとしてメタデータでマークされている依存関係プロパティの値が変更された場合。

可能な場合は最も効率的なパネルを使用する

使用する Panel 派生要素のレイアウト動作はレイアウト プロセスの複雑さに直接影響します。 たとえば、Grid コントロールや StackPanel コントロールには Canvas コントロールよりはるかに多くの機能が用意されていますが、 その代償として、パフォーマンスへの負荷も高くなります。 Grid コントロールに用意されている機能が必要ない場合は、Canvas やカスタム パネルなど、パフォーマンスへの負荷が低いコントロールを代わりに使用するようにしてください。

詳細については、「パネルの概要」を参照してください。

RenderTransform は置き換えずに更新する

RenderTransform プロパティの値として、Transform を置き換えずに更新できる場合があります。 アニメーションを含むシナリオでは特にこれが当てはまります。 既存の Transform を更新すると、不要なレイアウト計算が開始されるのを防ぐことができます。

ツリーはトップダウンで作成する

論理ツリーのノードが追加または削除されると、ノードの親とそのすべての子でプロパティの無効化が行われます。 このため、常にトップダウンの作成パターンに従って、検証済みのノードで無駄に無効化が行われないようにする必要があります。 ツリーをトップダウンで作成した場合とボトムアップで作成した場合の実行速度の違いを次の表に示します。このツリーには 150 のレベルがあり、各レベルに TextBlockDockPanel が 1 つずつ含まれています。

アクション

ツリーの作成 (ミリ秒)

レンダリング — ツリーの作成を含む (ミリ秒)

ボトムアップ

366

454

トップダウン

11

96

ツリーをトップダウンで作成する方法を次のコード例に示します。

        Private Sub OnBuildTreeTopDown(ByVal sender As Object, ByVal e As RoutedEventArgs)
            Dim textBlock As New TextBlock()
            textBlock.Text = "Default"

            Dim parentPanel As New DockPanel()
            Dim childPanel As DockPanel

            myCanvas.Children.Add(parentPanel)
            myCanvas.Children.Add(textBlock)

            For i As Integer = 0 To 149
                textBlock = New TextBlock()
                textBlock.Text = "Default"
                parentPanel.Children.Add(textBlock)

                childPanel = New DockPanel()
                parentPanel.Children.Add(childPanel)
                parentPanel = childPanel
            Next i
        End Sub
private void OnBuildTreeTopDown(object sender, RoutedEventArgs e)
{
    TextBlock textBlock = new TextBlock();
    textBlock.Text = "Default";

    DockPanel parentPanel = new DockPanel();
    DockPanel childPanel;

    myCanvas.Children.Add(parentPanel);
    myCanvas.Children.Add(textBlock);

    for (int i = 0; i < 150; i++)
    {
        textBlock = new TextBlock();
        textBlock.Text = "Default";
        parentPanel.Children.Add(textBlock);

        childPanel = new DockPanel();
        parentPanel.Children.Add(childPanel);
        parentPanel = childPanel;
    }
}

論理ツリーの詳細については、「WPF のツリー」を参照してください。

参照

概念

WPF アプリケーションのパフォーマンスの最適化

アプリケーション パフォーマンスの計画

パフォーマンスの最適化 : ハードウェアの活用

パフォーマンスの最適化 : 2D グラフィックスとイメージング

パフォーマンスの最適化 : オブジェクトの動作

パフォーマンスの最適化 : アプリケーション リソース

パフォーマンスの最適化 : テキスト

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

パフォーマンスの最適化 : その他の推奨事項

レイアウト システム