必要なレイアウトに複数のパネルが適している場合は何度もありますが、パネルの種類によってレンダリング時間が異なることがわかっています。
たとえば、 [〜#〜] msdn [〜#〜] は
Panel
などの比較的単純なCanvas
は、Panel
などのより複雑なGrid
よりもパフォーマンスが大幅に向上します。
では、レンダリング時間とパフォーマンスの観点から、WPFパネルはどの順序で最も効率的ですか?
WPFパネル:
Canvas
DockPanel
Grid
UniformGrid
StackPanel
WrapPanel
VirtualizingPanel
/VirtualizingStackPanel
このリストはオンラインのどこかで見たはずですが、今は見つけることができません。
私が探している理想的な答えは、パネルのリストを、それらが最も速くレンダリングされる順序で提供することです。子の数がパネルの効率を左右する大きな要因であると理解しているため、この質問のために、各パネルにはLabel
/TextBox
ペアのみがあると仮定します。
さらに、特定の条件に基づいて他のパネルよりもパフォーマンスが向上する特定のパネルなど、例外のリストが必要です。
更新
承認済みの回答 に基づいて要約すると、パネルのパフォーマンスは子アイテムの数とレイアウトに基づいていますが、一般的には、最速から最速までのリストは次のとおりです。
Canvas
StackPanel
WrapPanel
DockPanel
Grid
さらに、常に画面に収まらないアイテムが多数ある場合は、VirtualizingPanel
/VirtualizingStackPanel
を常に使用する必要があります。
このリストからアイテムを選択する前に、詳細については、以下の 承認済みの回答 を読むことを強くお勧めします。
各パネルのパフォーマンス特性を説明する方が、相対的なパフォーマンスを絶対的に比較しようとするよりも、簡潔で理解しやすいと思います。
WPFは、コンテンツのレンダリング時に2つのパス、MeasureとArrangeを作成します。各パネルには、これらの2つのパスごとに異なるパフォーマンス特性があります。
メジャーパスのパフォーマンスは、配置(または[Grid
の場合は自動)を使用したストレッチに対応するパネルの機能と、ストレッチまたは自動サイズ調整される子の数によって最も影響を受けます。アレンジパスのパフォーマンスは、異なる子のレイアウト位置と、もちろん子の数との間の相互作用の複雑さの影響を受けます。
時には、与えられたパネルは必要なレイアウトに簡単に役立たないことがあります。使用可能なスペースの特定の割合に配置するために、任意の数のアイテムを必要とするコントロールを作成しました。これを行うデフォルトのコントロールはありません。 (親の実際のサイズへのバインドを介して)これを実行しようとすると、ひどいパフォーマンスになります。キャンバスに基づいてレイアウトパネルを作成し、最小限の作業で目的の結果を達成しました(キャンバスのソースをコピーし、約20行変更しました)。
利用可能なパネル:
キャンバス
Canvas領域を基準にした座標によって子要素を明示的に配置できる領域を定義します。
キャンバスは、各アイテムに静的に位置が割り当てられているため、配置パスのすべてのパネルの中で最高のパフォーマンスを発揮します。このパネルにはストレッチの概念がないため、メジャーパスのパフォーマンスも優れています。各子は、単純にネイティブサイズを使用します。
DockPanel
子要素を相互に水平または垂直に配置できる領域を定義します。
Dockpanelには非常にシンプルなレイアウトスキームがあり、アイテムは1つ前に追加されたアイテムに対して1つずつ追加されます。デフォルトでは、高さまたは幅のいずれかはアイテムのネイティブサイズ(上/下vs左/右にそれぞれ基づく)によって決定され、幅または高さが定義されていない場合、他の方向はDock
プロパティによって決定されます。中から高速の測定パスおよび中から高速の配置パス。
グリッド
列と行で構成される柔軟なグリッド領域を定義します。
比例サイジングまたは自動サイジングが使用されている場合、これは最もパフォーマンスが集中するパネルになります。子アイテムのサイズの計算は、アイテムのネイティブサイズとグリッドで指定されたレイアウトの複雑な組み合わせにすることができます。また、レイアウトはすべてのパネルの中で最も複雑です。メジャーパスでは低速から中程度のパフォーマンス、アレンジメントパスでは低速から中程度のパフォーマンス。
StackPanel
子要素を、水平方向または垂直方向に配置できる単一の行に配置します。
StackPanelは、その方向とは反対方向のネイティブまたは相対サイズと、その方向のネイティブサイズを使用して子を測定します(この方向では整列は何も行いません)。これにより、この分野の中間レベルのパフォーマーになります。アレンジメントパスは、単にアイテムを順番に配置するだけです。おそらく、このパスで2番目に良いパフォーマンスです。測定パスでは中程度のパフォーマンス、レイアウトパスでは高速のパフォーマンス。
VirtualizingPanel
子データコレクションを仮想化するPanel要素のフレームワークを提供します。これは抽象クラスです。
独自の仮想化パネルを実装するための基本クラス。メモリとプロセッサの不必要な使用を防ぐために、可視アイテムのみをロードします。アイテムセットのパフォーマンスが大幅に向上しました。境界チェックのために、画面に収まるアイテムのパフォーマンスがおそらくわずかに低下します。 SDKは、VirtualizingStackPanel
というサブクラスを1つだけ提供します。
WrapPanel
子要素を左から右に連続した位置に配置し、コンテンツを含むボックスのエッジで次の行にコンテンツを分割します。その後の順序は、Orientationプロパティの値に応じて、上から下または右から左に順番に発生します。
メジャーパスはやや複雑なパスで、特定の行の最大アイテムが行の高さを決定し、その行の各アイテムがネイティブの高さ(ある場合)または行の高さを使用します。レイアウトパスは単純で、各アイテムを1つの行に次々に配置し、次のアイテムに十分なスペースがないときに次の行に進みます。中程度のパフォーマンス測定パス。アレンジメントパスの中程度から高速のパフォーマンス。
参照:
可能な限り最も効率的なパネルを使用する
レイアウトプロセスの複雑さは、使用するPanel派生要素のレイアウト動作に直接基づいています。たとえば、GridまたはStackPanelコントロールは、Canvasコントロールよりもはるかに多くの機能を提供します。この機能の大幅な増加の代償は、パフォーマンスコストの大幅な増加です。ただし、Gridコントロールが提供する機能が必要ない場合は、Canvasやカスタムパネルなど、コストの低い代替手段を使用する必要があります。
レイアウトシステムは、Childrenコレクションの各メンバーに対して、メジャーパスとアレンジパスの2つのパスを完了します。各子パネルは、独自の特定のレイアウト動作を実現するために、独自のMeasureOverrideおよびArrangeOverrideメソッドを提供します。
メジャーパス中に、Childrenコレクションの各メンバーが評価されます。プロセスは、Measureメソッドの呼び出しで始まります。このメソッドは、親Panel要素の実装内で呼び出され、レイアウトを発生させるために明示的に呼び出す必要はありません。
最初に、ClipやVisibilityなど、UIElementのネイティブサイズプロパティが評価されます。これにより、constraintSizeという名前の値が生成され、MeasureCoreに渡されます。
次に、FrameworkElementで定義されたフレームワークプロパティが処理され、constraintSizeの値に影響します。通常、これらのプロパティは、高さ、幅、余白、スタイルなど、基になるUIElementのサイズ設定特性を記述します。これらの各プロパティは、要素を表示するために必要なスペースを変更できます。次に、constraintSizeをパラメーターとして指定して、MeasureOverrideが呼び出されます。
注HeightとWidthのプロパティとActualHeightとActualWidthのプロパティには違いがあります。たとえば、ActualHeightプロパティは、他の高さ入力とレイアウトシステムに基づいて計算された値です。値は、実際のレンダリングパスに基づいてレイアウトシステム自体によって設定されるため、入力の変更の基礎となるHeightなどのプロパティの設定値よりもわずかに遅れることがあります。 ActualHeightは計算値であるため、レイアウトシステムによるさまざまな操作の結果、ActualHeightに複数または増分の変更が報告される可能性があることに注意する必要があります。レイアウトシステムは、子要素に必要なメジャースペース、親要素による制約などを計算している場合があります。測定パスの最終的な目標は、子がDesiredSizeを決定することです。これは、MeasureCore呼び出し中に発生します。 DesiredSize値は、コンテンツアレンジパス中に使用するためにMeasureによって保存されます。
配置パスは、Arrangeメソッドの呼び出しで始まります。配置パス中に、親のPanel要素は、子の境界を表す長方形を生成します。この値は、処理のためにArrangeCoreメソッドに渡されます。
ArrangeCoreメソッドは、子のDesiredSizeを評価し、要素のレンダリングサイズに影響する可能性のある追加のマージンを評価します。 ArrangeCoreは、arrangeSizeを生成し、PanelのArrangeOverrideメソッドにパラメーターとして渡します。 ArrangeOverrideは、子のfinalSizeを生成します。最後に、ArrangeCoreメソッドは、マージンや配置などのオフセットプロパティの最終評価を行い、子をレイアウトスロット内に配置します。子は、割り当てられたスペース全体を埋める必要はありません(頻繁に満たす必要もありません)。次に、コントロールが親パネルに返され、レイアウトプロセスが完了します。
多分 this が助けになるでしょう。
パネルだけでなく、WPFで作成するすべてのアプリケーションにも使用できます。
WPFの描画とパフォーマンスの測定を終了します。
また、ターゲットにするさまざまなオペレーティングシステムの描画テストアプリケーション、結果、および結論情報も含まれています。
あなたが言及するパネルはレイアウトパネルですので、レイアウトシステムの簡単な概要は、最も効率的なパネルの単なるリストではなく、効率とパフォーマンスに最大の影響を与えるパネルの使用方法である可能性が高いことを示唆しています。
最も単純なレイアウトは、要素のサイズ変更、配置、描画を行う再帰的なシステムです。より具体的には、レイアウトは、Panel要素のChildrenコレクションのメンバーを測定および配置するプロセスを表します。レイアウトは集中的なプロセスです。 Childrenコレクションが大きいほど、実行する必要がある計算の数が多くなります。コレクションを所有するPanel要素によって定義されたレイアウト動作に基づいて、複雑さを導入することもできます。 Canvasなどの比較的単純なパネルは、Gridなどのより複雑なパネルよりもパフォーマンスが大幅に向上する可能性があります。
子UIElementが位置を変更するたびに、レイアウトシステムによる新しいパスをトリガーする可能性があります。したがって、不必要な呼び出しはアプリケーションのパフォーマンス低下につながる可能性があるため、レイアウトシステムを呼び出すことができるイベントを理解することが重要です。次に、レイアウトシステムが呼び出されたときに発生するプロセスについて説明します。
1.子UIElementは、最初にコアプロパティを測定することにより、レイアウトプロセスを開始します。
2.幅、高さ、マージンなど、FrameworkElementで定義されたサイズ設定プロパティが評価されます。
3.ドックの方向や積み重ねの向きなど、パネル固有のロジックが適用されます。
4.コンテンツは、すべての子供が測定された後に配置されます。
5. Childrenコレクションが画面に描画されます。
6.追加の子がコレクションに追加されるか、LayoutTransformが適用されるか、UpdateLayoutメソッドが呼び出されると、プロセスが再度呼び出されます。
子の測定と配置の詳細については、 LayoutSystem_Measure_Arrange を参照してください
レイアウトは再帰的なプロセスです。 Childrenコレクションの各子要素は、レイアウトシステムの各呼び出し中に処理されます。その結果、レイアウトシステムのトリガーは、必要でない場合は回避する必要があります。次の考慮事項は、パフォーマンスの向上に役立ちます。
どのプロパティ値が変更されると、レイアウトシステムによる再帰的な更新が強制されることに注意してください。
値がレイアウトシステムの初期化を引き起こす可能性のある依存関係プロパティは、パブリックフラグでマークされます。 AffectsMeasureとAffectsArrangeは、どのプロパティ値の変更がレイアウトシステムによる再帰的な更新を強制するかに関する有用な手がかりを提供します。一般に、要素の境界ボックスのサイズに影響を与える可能性のあるプロパティには、AffectsMeasureフラグをtrueに設定する必要があります。詳細については、「依存関係プロパティの概要」を参照してください。
可能であれば、LayoutTransformの代わりにRenderTransformを使用してください。
LayoutTransformは、ユーザーインターフェイス(UI)のコンテンツに影響を与える非常に便利な方法です。ただし、変換の効果が他の要素の位置に影響を与える必要がない場合、RenderTransformはレイアウトシステムを呼び出さないため、代わりにRenderTransformを使用するのが最善です。 LayoutTransformは変換を適用し、影響を受ける要素の新しい位置を考慮して再帰的なレイアウト更新を強制します。
UpdateLayoutの不要な呼び出しを避けます。
UpdateLayoutメソッドは、再帰的なレイアウト更新を強制するため、頻繁に必要ではありません。完全な更新が必要であることが確実でない限り、レイアウトシステムに依存してこのメソッドを呼び出してください。
大きなChildrenコレクションを使用する場合は、通常のStackPanelではなくVirtualizingStackPanelの使用を検討してください。
子コレクションを仮想化することにより、VirtualizingStackPanelは、現在親のViewPort内にあるオブジェクトのみをメモリに保持します。その結果、ほとんどのシナリオでパフォーマンスが大幅に向上します。
パフォーマンスの最適化:レイアウトとデザイン :この記事では、ツリーを効率的に構築する方法について詳しく説明し、複雑さに基づいたパネルの簡単なリストを示します。
Canvas(最も複雑でない=より効率的でパフォーマンスが向上)
グリッド
その他のパネル(より複雑=効率が悪く、パフォーマンスが低下)
他のパフォーマンスの考慮事項に注意する必要があります:WPF UIレンダリング速度を改善する方法