布局
面板(Panel)
Avalonia 包含一组派生自 Panel
的元素。这些 Panel
元素可实现许多复杂的布局。例如,可以使用 StackPanel
元素 轻松地堆叠元素,而使用 Canvas
则可以实现更复杂和自由流动的布局。
以下表格总结了可用的 Panel
控件:
名称 | 描述 |
---|---|
Panel | 将所有子元素布局以填充 Panel 的边界 |
Canvas | 定义一个区域,您可以在其中使用相对于 Canvas 区域的坐标明确定位子元素 |
DockPanel | 定义一个区域,其中您可以相对于彼此将子元素水平或垂直地排列 |
Grid | 定义由列和行组成的灵活网格区域 |
RelativePanel | 将子元素相对于其他元素或面板本身排列 |
StackPanel | 将子元素排列成一行,可以是水平或垂直方向 |
WrapPanel | 将子元素按从左到右的顺序放置,当内容到达容器框的边缘时,将在下一行中断。后续排序顺序是顺序从上到下或从右到左,这取决于 Orientation 属性的值。 |
在 WPF 中,Panel
是一个抽象类,通常使用没有行/列的 Grid
来布局多个控件以填充可用空间。在 Avalonia 中,Panel
是一个可用的控件,其布局行为与没有行/列的 Grid
相同,但运行时占用更少的资源。
元素边界框
在考虑 Avalonia 中的布局时,了解包围所有元素的边界框很重要。布局系统处理的每个 Control
可以看作是一个矩形,该矩形被插入布局。Bounds
属性返回元素布局分配的边界。矩形的大小 通过计算可用的屏幕空间、任何约束的大小、布局特定属性(如 margin 和 padding)以及父 Panel
元素的个体行为来确定。处理这些数据,布局系统能够计算特定 Panel
的所有子元素的位置。重要的是要记住,定义在父元素上的大小特性,例如 Border
上的特性,会影响其子元素。
布局系统
简单来说,布局是一种递归系统,导致元素被大小化、定位和绘制。更具体地说,布局描述了对 Panel
元素的 Children
集合的成员进行测量和排列的过程。布局是一个密集的过程。Children
集合越大,必须进行的计算越多。还可以根据拥有集合的 Panel
元素定义的布局行为引入复杂性。一个相对简单的 Panel
,例如 Canvas
,可以比一个更复杂的 Panel
,例如 Grid
,具有更好的性能。
每次子控件更改其位置时,它都有可能触发布局系统的新传递。因此,了解可以调用布局系统的事件很重要,因为不必要的调用可能会导致应用程序性能下降。下面描述了在调用布局系统时发生的过程。
- 子 UIElement 通过首先测量其核心属性来开始布局过程。
- 评估在
Control
上定义的大小属性,例如Width
、Height
和Margin
。 - 应用
Panel
特定的逻辑,例如Dock
方向或堆叠的Orientation
。 - 在所有子元素进行测量后,进行内容的排列。
- 在屏幕上绘制
Children
集合。 - 如果向集合中添加了其他
Children
,则再次调用此过程。
此过程及其调用方式在以下部分中有更详细的定义。
测量和排列子元素
布局系统对 Children
集合的每个成员完成两个传递:测量传递和排列传递。每个子 Panel
提供其自己的 MeasureOverride
和 ArrangeOverride
方法,以实现其自己的特定布局行为。
在测量传递期间,对 Children
集合的每个成员进行评估。该过程从调用 Measure
方法开始。此方法在父 Panel
元素的实现中调用,不必显式调用以进行布局。
首先,评估 Visual
的本机大小属性,例如 Clip
和 IsVisible
。这将生成传递给 MeasureCore
的约束。
然后,处理影响约束值的框架属性。这些属性通常描述底层 Control
的大小特性,例如其 Height
、Width
和 Margin
。每个这些属性都可以改变显示元素所需的空间。然后,使用约束调用 MeasureOverride
。
由于 Bounds
是计算值,因此您应该注意,由于布局系统的各种操作,它可能会发生多次或增量的报告更改。布局系统可能正在为子元素计算所需的测量空间、父元素的约束等。
测量传递的最终目标是让子元素确定其 DesiredSize
,这在 MeasureCore
调用期间发生。Measure
将 DesiredSize
值存储以在内容排列传递中使用。
排列传递从调用 Arrange
方法开始。在排列传递期间,父 Panel
元素生成表示子元素边界的矩形。该值 传递给 ArrangeCore
方法进行处理。
ArrangeCore
方法评估子元素的 DesiredSize
,并评估任何可能影响元素渲染大小的附加 margin
。ArrangeCore
生成一个排列大小,将其作为参数传递给 Panel
的 ArrangeOverride
方法。ArrangeOverride
生成子元素的 finalSize
。最后,ArrangeCore
方法对边距和对齐等偏移属性进行最后评估,并将子元素放置在其布局插槽中。子元素不必(也经常不会)填充整个分配的空间。然后,将控件返回给父 Panel
,布局过程完成。