レイアウトLayout

このトピックでは、Windows Presentation Foundation (WPF) レイアウトシステムについて説明します。This topic describes the Windows Presentation Foundation (WPF) layout system. WPF でユーザーインターフェイスを作成するには、レイアウトの計算がどのように行われるかを理解することが不可欠です。Understanding how and when layout calculations occur is essential for creating user interfaces in WPF.

このトピックは、次のセクションで構成されています。This topic contains the following sections:

要素の境界ボックスElement Bounding Boxes

WPF でのレイアウトについて考えるときは、すべての要素を囲む境界ボックスについて理解しておくことが重要です。When thinking about layout in WPF, it is important to understand the bounding box that surrounds all elements. レイアウトFrameworkElementシステムによって使用される各は、レイアウトにスロット分割される四角形と考えることができます。Each FrameworkElement consumed by the layout system can be thought of as a rectangle that is slotted into the layout. クラスLayoutInformationは、要素のレイアウト割り当て (スロット) の境界を返します。The LayoutInformation class returns the boundaries of an element's layout allocation, or slot. 四角形のサイズは、使用可能な画面領域、制約のサイズ、レイアウト固有のプロパティ (余白や埋め込みなど)、および親Panel要素の個々の動作を計算することによって決定されます。The size of the rectangle is determined by calculating the available screen space, the size of any constraints, layout-specific properties (such as margin and padding), and the individual behavior of the parent Panel element. レイアウトシステムは、このデータを処理することで、特定Panelののすべての子の位置を計算できます。Processing this data, the layout system is able to calculate the position of all the children of a particular Panel. Borderように、親要素で定義されているサイズ設定特性は、その子に影響を与えることに注意してください。It is important to remember that sizing characteristics defined on the parent element, such as a Border, affect its children.

次の図は、シンプルなレイアウトを示しています。The following illustration shows a simple layout.

一般的なグリッドを示すスクリーンショット。境界ボックスは重ねて表示されません。

このレイアウトは、次の XAMLXAML を使用して実現できます。This layout can be achieved by using the following XAMLXAML.

<Grid Name="myGrid" Background="LightSteelBlue" Height="150">
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="250"/>
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition />
    <RowDefinition />
  </Grid.RowDefinitions>
  <TextBlock Name="txt1" Margin="5" FontSize="16" FontFamily="Verdana" Grid.Column="0" Grid.Row="0">Hello World!</TextBlock>
  <Button Click="getLayoutSlot1" Width="125" Height="25" Grid.Column="0" Grid.Row="1">Show Bounding Box</Button>
  <TextBlock Name="txt2" Grid.Column="1" Grid.Row="2"/>
</Grid>

1つTextBlockの要素がGrid内でホストされます。A single TextBlock element is hosted within a Grid. テキストは最初の列の左上隅にのみ表示TextBlockされますが、の割り当て済み領域は実際には非常に大きくなります。While the text fills only the upper-left corner of the first column, the allocated space for the TextBlock is actually much larger. 任意FrameworkElementのの境界ボックスは、 GetLayoutSlotメソッドを使用して取得できます。The bounding box of any FrameworkElement can be retrieved by using the GetLayoutSlot method. TextBlock要素の境界ボックスを次の図に示します。The following illustration shows the bounding box for the TextBlock element.

TextBlock 境界ボックスが表示されていることを示すスクリーンショット。

黄色の四角形で示されているように、 TextBlock要素に割り当てられた領域は、実際には表示されるよりもはるかに大きくなります。As shown by the yellow rectangle, the allocated space for the TextBlock element is actually much larger than it appears. 追加の要素がにGrid追加されると、追加される要素の型とサイズに応じて、この割り当てが縮小または拡張される可能性があります。As additional elements are added to the Grid, this allocation could shrink or expand, depending on the type and size of elements that are added.

TextBlockレイアウトスロットは、 GetLayoutSlotメソッドを使用しPathてに変換されます。The layout slot of the TextBlock is translated into a Path by using the GetLayoutSlot method. この方法は、要素の境界ボックスの表示に役立ちます。This technique can be useful for displaying the bounding box of an element.

private void getLayoutSlot1(object sender, System.Windows.RoutedEventArgs e)
{
    RectangleGeometry myRectangleGeometry = new RectangleGeometry();
    myRectangleGeometry.Rect = LayoutInformation.GetLayoutSlot(txt1);
    Path myPath = new Path();
    myPath.Data = myRectangleGeometry;
    myPath.Stroke = Brushes.LightGoldenrodYellow;
    myPath.StrokeThickness = 5;
    Grid.SetColumn(myPath, 0);
    Grid.SetRow(myPath, 0);
    myGrid.Children.Add(myPath);
    txt2.Text = "LayoutSlot is equal to " + LayoutInformation.GetLayoutSlot(txt1).ToString();
}
Private Sub getLayoutSlot1(ByVal sender As Object, ByVal e As RoutedEventArgs)
    Dim myRectangleGeometry As New RectangleGeometry
    myRectangleGeometry.Rect = LayoutInformation.GetLayoutSlot(txt1)
    Dim myPath As New Path
    myPath.Data = myRectangleGeometry
    myPath.Stroke = Brushes.LightGoldenrodYellow
    myPath.StrokeThickness = 5
    Grid.SetColumn(myPath, 0)
    Grid.SetRow(myPath, 0)
    myGrid.Children.Add(myPath)
    txt2.Text = "LayoutSlot is equal to " + LayoutInformation.GetLayoutSlot(txt1).ToString()
End Sub

レイアウト システムThe Layout System

簡単に言うと、レイアウトは、要素のサイズ測定、配置、および描画を繰り返す再帰的なシステムです。At its simplest, layout is a recursive system that leads to an element being sized, positioned, and drawn. 具体的には、レイアウトは、要素のPanel Childrenコレクションのメンバーを測定および整列するプロセスについて説明します。More specifically, layout describes the process of measuring and arranging the members of a Panel element's Children collection. レイアウトは集中的なプロセスです。Layout is an intensive process. コレクションがChildren大きいほど、作成する必要がある計算の数が多くなります。The larger the Children collection, the greater the number of calculations that must be made. また、コレクションを所有するPanel要素によって定義されたレイアウトの動作に基づいて、複雑さを導入することもできます。Complexity can also be introduced based on the layout behavior defined by the Panel element that owns the collection. など、比較的Panel単純Canvasなでは、より複雑Panel Gridなパフォーマンスを大幅に向上させることができます。A relatively simple Panel, such as Canvas, can have significantly better performance than a more complex Panel, such as Grid.

UIElementがその位置を変更するたびに、レイアウトシステムによって新しいパスがトリガーされる可能性があります。Each time that a child UIElement changes its position, it has the potential to trigger a new pass by the layout system. したがって、不要な呼び出しはアプリケーション パフォーマンスの低下につながる可能性があるため、レイアウト システムを呼び出す可能性があるイベントを理解することが重要です。Therefore, it is important to understand the events that can invoke the layout system, as unnecessary invocation can lead to poor application performance. 以下に、レイアウト システムが呼び出されたときに発生するプロセスについて説明します。The following describes the process that occurs when the layout system is invoked.

  1. UIElementは、最初にコアプロパティを測定して、レイアウトプロセスを開始します。A child UIElement begins the layout process by first having its core properties measured.

  2. WidthFrameworkElement 、など、で定義されたサイズ変更プロパティが評価されます。Height MarginSizing properties defined on FrameworkElement are evaluated, such as Width, Height, and Margin.

  3. PanelDock方向やスタックOrientationなど、固有のロジックが適用されます。Panel-specific logic is applied, such as Dock direction or stacking Orientation.

  4. すべての子が測定された後にコンテンツが配置されます。Content is arranged after all children have been measured.

  5. Childrenコレクションが画面に描画されます。The Children collection is drawn on the screen.

  6. 追加Childrenがコレクションに追加された場合LayoutTransformUpdateLayoutが適用された場合、またはメソッドが呼び出された場合は、プロセスが再度呼び出されます。The process is invoked again if additional Children are added to the collection, a LayoutTransform is applied, or the UpdateLayout method is called.

このプロセスとその呼び出し方法は、次のセクションで詳細に定義します。This process and how it is invoked are defined in more detail in the following sections.

子の測定と配置Measuring and Arranging Children

レイアウトシステムは、 Childrenコレクションのメンバーごとに、測定パスと配置パスの2つのパスを完了します。The layout system completes two passes for each member of the Children collection, a measure pass and an arrange pass. 各子PanelにはMeasureOverride 、独自ArrangeOverrideの特定のレイアウト動作を実現するためのメソッドとメソッドが用意されています。Each child Panel provides its own MeasureOverride and ArrangeOverride methods to achieve its own specific layout behavior.

メジャーパスの実行中に、 Childrenコレクションの各メンバーが評価されます。During the measure pass, each member of the Children collection is evaluated. プロセスは、メソッドのMeasure呼び出しで開始されます。The process begins with a call to the Measure method. このメソッドは、親Panel要素の実装内で呼び出されます。レイアウトを行うには、明示的に呼び出す必要はありません。This method is called within the implementation of the parent Panel element, and does not have to be called explicitly for layout to occur.

最初に、のUIElementネイティブサイズプロパティが評価されます ( Visibility Clipやなど)。First, native size properties of the UIElement are evaluated, such as Clip and Visibility. これにより、にconstraintSize MeasureCore渡されるという名前の値が生成されます。This generates a value named constraintSize that is passed to MeasureCore.

2番目の方法とFrameworkElementして、に定義されてconstraintSizeいるフレームワークプロパティが処理され、の値に影響します。Secondly, framework properties defined on FrameworkElement are processed, which affects the value of constraintSize. これらのUIElementプロパティはHeightWidth通常、Style、、 、など、基になるのサイズ設定特性を記述します。MarginThese properties generally describe the sizing characteristics of the underlying UIElement, such as its Height, Width, Margin, and Style. これらの各プロパティは、要素を表示するために必要な領域を変更できます。Each of these properties can change the space that is necessary to display the element. MeasureOverrideは、パラメーターとconstraintSizeしてで呼び出されます。MeasureOverride is then called with constraintSize as a parameter.

注意

HeightのプロパティとのWidth ActualHeight間には違いがあります。ActualWidthThere is a difference between the properties of Height and Width and ActualHeight and ActualWidth. たとえばActualHeight 、プロパティは、他の高さ入力およびレイアウトシステムに基づく計算値です。For example, the ActualHeight property is a calculated value based on other height inputs and the layout system. 値は、実際のレンダリングパスに基づいてレイアウトシステム自体によって設定されます。したがって、入力の変更の基礎となるHeight、などのプロパティの設定値よりも少し遅れが生じることがあります。The value is set by the layout system itself, based on an actual rendering pass, and may therefore lag slightly behind the set value of properties, such as Height, that are the basis of the input change.

ActualHeight計算値であるため、レイアウトシステムによるさまざまな操作の結果として、複数のまたは増分の報告される変更がある可能性があることに注意してください。Because ActualHeight is a calculated value, you should be aware that there could be multiple or incremental reported changes to it as a result of various operations by the layout system. レイアウト システムが、子要素に必要な測定スペース、親要素による制約などを計算している場合があります。The layout system may be calculating required measure space for child elements, constraints by the parent element, and so on.

メジャーパスの最終的な目標は、子がDesiredSize MeasureCore呼び出し中に発生するを決定することです。The ultimate goal of the measure pass is for the child to determine its DesiredSize, which occurs during the MeasureCore call. 値は、コンテンツのMeasure配置パス中に使用するためにによって格納されます。 DesiredSizeThe DesiredSize value is stored by Measure for use during the content arrange pass.

配置パスは、メソッドのArrange呼び出しで始まります。The arrange pass begins with a call to the Arrange method. 配置パス中に、親Panel要素は、子の境界を表す四角形を生成します。During the arrange pass, the parent Panel element generates a rectangle that represents the bounds of the child. この値は、 ArrangeCore処理のためにメソッドに渡されます。This value is passed to the ArrangeCore method for processing.

メソッドArrangeCoreは、子DesiredSizeのを評価し、表示される要素のサイズに影響する可能性のある追加の余白を評価します。The ArrangeCore method evaluates the DesiredSize of the child and evaluates any additional margins that may affect the rendered size of the element. ArrangeCoreを生成します。これは、 ArrangeOverride Panelパラメーターとしてのメソッドに渡されます。 arrangeSizeArrangeCore generates an arrangeSize, which is passed to the ArrangeOverride method of the Panel as a parameter. ArrangeOverridefinalSize子のを生成します。ArrangeOverride generates the finalSize of the child. 最後に、 ArrangeCoreメソッドは、余白や配置などのオフセットプロパティの最終的な評価を行い、子をレイアウトスロット内に配置します。Finally, the ArrangeCore method does a final evaluation of offset properties, such as margin and alignment, and puts the child within its layout slot. 子は割り当てられた領域全体を埋める必要はありません (そうしない場合もよくあります)。The child does not have to (and frequently does not) fill the entire allocated space. 次に、コントロールが親Panelに返され、レイアウトプロセスが完了します。Control is then returned to the parent Panel and the layout process is complete.

パネル要素とカスタム レイアウトの動作Panel Elements and Custom Layout Behaviors

WPF には、からPanel派生する要素のグループが含まれています。WPF includes a group of elements that derive from Panel. これらPanelの要素により、多数の複雑なレイアウトが可能になります。These Panel elements enable many complex layouts. たとえば、 StackPanel要素を使用すると、積み重ねる要素を簡単に実現できます。一方、をCanvas使用すると、より複雑でフリーのフローレイアウトが可能になります。For example, stacking elements can easily be achieved by using the StackPanel element, while more complex and free flowing layouts are possible by using a Canvas.

次の表は、使用可能Panelなレイアウト要素をまとめたものです。The following table summarizes the available layout Panel elements.

パネル名Panel name 説明Description
Canvas Canvas領域を基準に相対的に子要素を相対的に配置できる領域を定義します。Defines an area within which you can explicitly position child elements by coordinates relative to the Canvas area.
DockPanel 子要素を互いに水平方向または垂直方向に整列する領域を定義します。Defines an area within which you can arrange child elements either horizontally or vertically, relative to each other.
Grid 行と列で構成される柔軟性のあるグリッド領域を定義します。Defines a flexible grid area that consists of columns and rows.
StackPanel 子要素を水平方向または垂直方向の単一行に整列します。Arranges child elements into a single line that can be oriented horizontally or vertically.
VirtualizingPanel 子データコレクションをPanel仮想化する要素のフレームワークを提供します。Provides a framework for Panel elements that virtualize their child data collection. これは抽象クラスです。This is an abstract class.
WrapPanel 左から右へ順に子要素を配置し、ボックスの端で改行してコンテンツを次の行へ送ります。Positions child elements in sequential position from left to right, breaking content to the next line at the edge of the containing box. 後続の順序は、 Orientationプロパティの値に応じて、上から下または右から左に順番に行われます。Subsequent ordering occurs sequentially from top to bottom or right to left, depending on the value of the Orientation property.

定義済みPanelの要素のいずれかを使用しても不可能なレイアウトを必要とするアプリケーションでは、をPanel継承し、メソッドMeasureOverrideArrangeOverrideメソッドをオーバーライドすることにより、カスタムレイアウト動作を実現できます。For applications that require a layout that is not possible by using any of the predefined Panel elements, custom layout behaviors can be achieved by inheriting from Panel and overriding the MeasureOverride and ArrangeOverride methods.

レイアウトのパフォーマンスの考慮事項Layout Performance Considerations

レイアウトは再帰的なプロセスです。Layout is a recursive process. Childrenコレクション内の各子要素は、レイアウトシステムの呼び出し中に処理されます。Each child element in a Children collection gets processed during each invocation of the layout system. そのため、必要ない場合はレイアウト システムをトリガーしないようにしてください。As a result, triggering the layout system should be avoided when it is not necessary. 次の考慮事項は、パフォーマンスを向上させるのに役立ちます。The following considerations can help you achieve better performance.

  • どのプロパティ値の変更がレイアウト システムによる再帰的な更新を強制するかに注意してください。Be aware of which property value changes will force a recursive update by the layout system.

    レイアウト システムを初期化できる値が設定されている依存関係プロパティは、パブリック フラグでマークされます。Dependency properties whose values can cause the layout system to be initialized are marked with public flags. AffectsMeasureAffectsArrangeは、レイアウトシステムによって強制的に再帰的に更新されるプロパティ値の変更に役立つ手掛かりを提供します。AffectsMeasure and AffectsArrange provide useful clues as to which property value changes will force a recursive update by the layout system. 一般に、要素の境界ボックスのサイズに影響を与える可能性のあるプロパティではAffectsMeasure 、フラグが true に設定されている必要があります。In general, any property that can affect the size of an element's bounding box should have a AffectsMeasure flag set to true. 依存関係プロパティの詳細については、「依存関係プロパティの概要」を参照してください。For more information, see Dependency Properties Overview.

  • 可能であれば、 RenderTransform LayoutTransformの代わりにを使用します。When possible, use a RenderTransform instead of a LayoutTransform.

    は、のコンテンツに影響を与える非常に便利な方法になります。ユーザー インターフェイス (UI)user interface (UI) LayoutTransformA LayoutTransform can be a very useful way to affect the content of a ユーザー インターフェイス (UI)user interface (UI). ただし、変換の効果が他の要素の位置に影響を与えない場合は、をRenderTransform使用することをお勧めします。これは、がレイアウトシステムを呼び出さないためRenderTransformです。However, if the effect of the transform does not have to impact the position of other elements, it is best to use a RenderTransform instead, because RenderTransform does not invoke the layout system. LayoutTransform変換を適用し、影響を受ける要素の新しい位置を考慮して、再帰的なレイアウトの更新を強制的に実行します。LayoutTransform applies its transformation and forces a recursive layout update to account for the new position of the affected element.

  • の不要な呼び出しUpdateLayoutを回避します。Avoid unnecessary calls to UpdateLayout.

    メソッドUpdateLayoutは、レイアウトの再帰的な更新を強制的に実行するため、頻繁には必要ありません。The UpdateLayout method forces a recursive layout update, and is frequently not necessary. 完全な更新が必要であると確信できる場合を除き、このメソッドの呼び出しはレイアウト システムに任せます。Unless you are sure that a full update is required, rely on the layout system to call this method for you.

  • 大きなChildrenコレクションを使用する場合は、通常StackPanelVirtualizingStackPanelではなくを使用することを検討してください。When working with a large Children collection, consider using a VirtualizingStackPanel instead of a regular StackPanel.

    子コレクションを仮想化することVirtualizingStackPanelにより、は、現在親のビューポート内にあるメモリ内のオブジェクトのみを保持します。By virtualizing the child collection, the VirtualizingStackPanel only keeps objects in memory that are currently within the parent's ViewPort. その結果、ほとんどのシナリオでパフォーマンスが大幅に向上します。As a result, performance is substantially improved in most scenarios.

サブピクセル レンダリングとレイアウトの丸め処理Sub-pixel Rendering and Layout Rounding

WPF グラフィックスシステムでは、デバイスに依存しない単位を使用して、解像度とデバイスに依存しないようにします。The WPF graphics system uses device-independent units to enable resolution and device independence. デバイスに依存しない各ピクセルは、システムのドット/インチ (dpi) 設定に応じて自動的にスケーリングされます。Each device independent pixel automatically scales with the system's dots per inch (dpi) setting. これにより、さまざまな dpi 設定に対して WPF アプリケーションの適切なスケーリングが提供され、アプリケーションが自動的に dpi に対応するようになります。This provides WPF applications proper scaling for different dpi settings and makes the application automatically dpi-aware.

ただし、この dpi に依存しない場合は、アンチエイリアシングのために不規則なエッジレンダリングが作成できます。However, this dpi independence can create irregular edge rendering because of anti-aliasing. これらの成果物 (通常はぼやけたエッジや半透明のエッジが見られます) は、エッジの場所がデバイス ピクセルの間ではなく、デバイス ピクセルの中間にある場合に発生します。These artifacts, typically seen as blurry or semi-transparent edges, can occur when the location of an edge falls in the middle of a device pixel instead of between device pixels. レイアウト システムは、レイアウトの丸め処理でこれを調整する方法を提供します。The layout system provides a way to adjust for this with layout rounding. レイアウトの丸め処理では、レイアウト システムがレイアウト パスの実行中に任意の整数以外のピクセル値を丸めます。Layout rounding is where the layout system rounds any non-integral pixel values during the layout pass.

レイアウトの丸め処理は既定で無効になっています。Layout rounding is disabled by default. レイアウトの丸め処理を有効にUseLayoutRoundingするにtrueは、 FrameworkElement任意のでプロパティをに設定します。To enable layout rounding, set the UseLayoutRounding property to true on any FrameworkElement. これは依存関係プロパティであるため、値はビジュアル ツリー内のすべての子に反映されます。Because it is a dependency property, the value will propagate to all the children in the visual tree. UI 全体のレイアウトの丸め処理を有効にUseLayoutRoundingするtrueには、ルートコンテナーのをに設定します。To enable layout rounding for the entire UI, set UseLayoutRounding to true on the root container. 例については、「UseLayoutRounding」を参照してください。For an example, see UseLayoutRounding.

次の内容What's Next

要素の測定方法と配置方法を理解することが、レイアウトを理解する最初のステップです。Understanding how elements are measured and arranged is the first step in understanding layout. 使用可能なPanel要素の詳細については、「パネルの概要」を参照してください。For more information about the available Panel elements, see Panels Overview. レイアウトに影響を与えるさまざまな配置プロパティをより理解するには、「配置、余白、パディングの概要」を参照してください。To better understand the various positioning properties that can affect layout, see Alignment, Margins, and Padding Overview. 軽量のアプリケーションにまとめて配置する準備ができたら、「 チュートリアル:初めての WPF デスクトップアプリケーション。When you are ready to put it all together in a lightweight application, see Walkthrough: My first WPF desktop application.

関連項目See also