布局面板
布局面板是用来为应用中的 UI 元素排列和分组的容器。 内置 XAML 布局面板包括 RelativePanel、StackPanel、Grid、VariableSizedWrapGrid 和 Canvas。 在这里,我们将介绍每个面板,并演示如何使用它来布局 XAML UI 元素。
选择布局面板时需要考虑以下几个事项:
- 面板如何定位其子元素。
- 面板如何调整其子元素的大小。
- 重叠子元素的分层方式(z 顺序)。
- 创建所需布局所需的嵌套面板元素的数量和复杂性。
示例
WinUI 2 库 | |
---|---|
如果已安装 WinUI 2 库应用,请参阅 RelativePanel、StackPanel、Grid、VariableSizedWrapGrid 和 Canvas。 |
面板属性
在讨论各个面板之前,让我们了解一下所有面板都具有的一些常见属性。
面板附加属性
大多数 XAML 布局面板使用附加属性让其子元素告知父面板如何在 UI 中定位它们。 附加属性使用语法 AttachedPropertyProvider.PropertyName。 如果面板嵌套在其他面板内,则仅由最直接的父面板解释指定布局特征的 UI 元素上的附加属性。
下面是有关如何在 XAML 中的 Button 控件上设置 Canvas.Left 附加属性的示例。 这会通知父画布,按钮应放置在画布左边缘 50 个有效像素。
<Canvas>
<Button Canvas.Left="50">Hello</Button>
</Canvas>
有关附加属性的详细信息,请参阅附加属性概述。
面板边框
RelativePanel、StackPanel 和网格面板定义边框属性,使你可以在面板周围绘制边框,而无需将它们包装到其他 Border 元素中。 边框属性为 BorderBrush、 BorderThickness、 CornerRadius 和 Padding。
下面是如何在网格上设置边框属性的示例。
<Grid BorderBrush="Blue" BorderThickness="12" CornerRadius="12" Padding="12">
<TextBlock Text="Hello World!"/>
</Grid>
使用内置边框属性可减少 XAML 元素计数,从而提高应用的 UI 性能。 有关布局面板和 UI 性能的详细信息,请参阅 “优化 XAML 布局”。
RelativePanel
RelativePanel 允许你设置 UI 元素的布局,方法是指定它们相对于其他元素的位置和相对于面板的位置。 默认情况下,元素位于面板的左上角。 可以将 RelativePanel 与 VisualStateManager 和 AdaptiveTrigger 一起使用,以针对不同的窗口大小重新排列 UI。
此表显示了可用于相对于面板或其他元素对齐某个元素的附加属性。
此 XAML 演示如何排列 RelativePanel 中的元素。
<RelativePanel BorderBrush="Gray" BorderThickness="1">
<Rectangle x:Name="RedRect" Fill="Red" Height="44" Width="44"/>
<Rectangle x:Name="BlueRect" Fill="Blue"
Height="44" Width="88"
RelativePanel.RightOf="RedRect" />
<Rectangle x:Name="GreenRect" Fill="Green"
Height="44"
RelativePanel.Below="RedRect"
RelativePanel.AlignLeftWith="RedRect"
RelativePanel.AlignRightWith="BlueRect"/>
<Rectangle Fill="Orange"
RelativePanel.Below="GreenRect"
RelativePanel.AlignLeftWith="BlueRect"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.AlignBottomWithPanel="True"/>
</RelativePanel>
结果如下所示。
以下是一些在调整矩形大小时需要注意的事项:
- 红色矩形的显式大小为 44x44。 它放置在面板的左上角,这是默认位置。
- 绿色矩形的显式高度为 44。 其左侧与红色矩形对齐,右侧与蓝色矩形对齐,确定其宽度。
- 橙色矩形未给定显式大小。 其左侧与蓝色矩形对齐。 它的右边缘和下边缘与面板的边缘对齐。 其大小由这些对齐方式确定,它将在调整面板大小时调整大小。
StackPanel
StackPanel 可以将其子元素按水平或垂直方向排列到单行中的布局面板。 StackPanel 通常用于在页面上排列一小部分 UI。
可以使用 Orientation 属性指定子元素的方向。 默认方向为 Vertical。
以下 XAML 演示如何创建项的垂直 StackPanel。
<StackPanel>
<Rectangle Fill="Red" Height="44"/>
<Rectangle Fill="Blue" Height="44"/>
<Rectangle Fill="Green" Height="44"/>
<Rectangle Fill="Orange" Height="44"/>
</StackPanel>
结果如下所示。
在 StackPanel 中,如果未显式设置子元素的大小,它将拉伸以填充可用宽度(或高度(如果方向为 水平)。 在此示例中,未设置矩形的宽度。 矩形展开以填充 StackPanel 的整个宽度。
网格
Grid 面板支持动态布局并允许你以多行或多列布局排列控件。 可以通过使用 RowDefinitions 和 ColumnDefinitions 属性来指定 Grid 的行和列。
要将对象放置到 Grid 的特定单元格中,请使用 Grid.Column 和 Grid.Row 附加属性。
要使内容分散到多个行和列中,请使用 Grid.RowSpan 和 Grid.ColumnSpan 附加属性。
此 XAML 示例演示如何创建包含两行和两列的网格。
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="44"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Rectangle Fill="Red" Width="44"/>
<Rectangle Fill="Blue" Grid.Row="1"/>
<Rectangle Fill="Green" Grid.Column="1"/>
<Rectangle Fill="Orange" Grid.Row="1" Grid.Column="1"/>
</Grid>
结果如下所示。
在此示例中,大小调整的工作方式如下所示:
- 第二行的显式高度为 44 个有效像素。 默认情况下,第一行的高度填充剩余的空间。
- 第一列的宽度设置为 “自动”,因此其子列的宽度是一样宽。 在这种情况下,宽度为 44 个有效像素,以容纳红色矩形的宽度。
- 矩形上没有其他大小限制,因此每个矩形都拉伸以填充其所属的网格单元格。
可以使用“自动”或“星型调整”在列或行内分配空间。 使用自动调整大小让 UI 元素调整大小以适应其内容或父容器。 还可以对网格的行和列使用自动大小调整。 若要使用自动大小调整,请将 UI 元素的高度和/或宽度设置为 “自动”。
使用比例大小调整(也称为 星型调整)按加权比例在网格的行和列之间分配可用空间。 在 XAML 中,比例缩放值用 * 表示(或使用 n* 表示加权比例缩放)。 例如,若要在两列布局中指定一列比另一列宽五倍,则在 ColumnDefinition 元素中对 Width 属性分别使用“5*”和“*”。
本示例将网格中的固定大小、自动大小和比例大小与 4 列组合在一起。
列 | 大小调整 | 说明 |
---|---|---|
Column_1 | Auto | 该列的大小将适合其内容。 |
Column_2 | * | 计算自动列后,该列将获取剩余宽度的一部分。 Column_2宽度为Column_4的一半。 |
Column_3 | 44 | 列宽为 44 像素。 |
Column_4 | 2* | 计算自动列后,该列将获取剩余宽度的一部分。 Column_4宽度为Column_2两倍。 |
默认列宽为“*”,因此无需为第二列显式设置此值。
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="44"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Column 1 sizes to its content." FontSize="24"/>
</Grid>
在 Visual Studio XAML 设计器中,结果如下所示。
VariableSizedWrapGrid
VariableSizedWrapGrid 是一个网格样式的布局面板,当达到 MaximumRowsOrColumns 值时,网格中的行或列会自动换行至新行或新列。
Orientation 属性指定网格在换行之前是否在行或列中添加其项。 默认方向为 Vertical,这意味着网格将项从上到下添加,直到列已满,然后换行到新列。 当值为 Horizontal 时,网格将项从左到右添加,然后换行到新行。
单元格维度由 ItemHeight 和 ItemWidth 指定。 每个单元格的大小相同。 如果未指定 ItemHeight 或 ItemWidth,则第一个单元格大小以适应其内容,而其他每个单元格都是第一个单元格的大小。
可以使用 VariableSizedWrapGrid.ColumnSpan 和 VariableSizedWrapGrid.RowSpan 附加属性来指定子元素应填充的相邻单元格数。
下面介绍如何在 XAML 中使用 VariableSizedWrapGrid。
<VariableSizedWrapGrid MaximumRowsOrColumns="3" ItemHeight="44" ItemWidth="44">
<Rectangle Fill="Red"/>
<Rectangle Fill="Blue"
VariableSizedWrapGrid.RowSpan="2"/>
<Rectangle Fill="Green"
VariableSizedWrapGrid.ColumnSpan="2"/>
<Rectangle Fill="Orange"
VariableSizedWrapGrid.RowSpan="2"
VariableSizedWrapGrid.ColumnSpan="2"/>
</VariableSizedWrapGrid>
结果如下所示。
在此示例中,每列中的最大行数为 3。 第一列仅包含 2 个项目(红色和蓝色矩形),因为蓝色矩形跨越 2 行。 然后,绿色矩形将换行到下一列的顶部。
画布
Canvas 面板使用固定的坐标点定位其子元素并且不支持动态布局。 可以通过在每个元素上设置 Canvas.Left 和 Canvas.Top 附加属性来指定各个子元素上的点。 父级 Canvas 在布局的 Arrange 传递期间从其子级中读取这些附加属性值。
Canvas 中的对象可以重叠,其中一个对象在另一个对象之上绘制。 默认情况下,Canvas 按声明子对象的顺序呈现子对象,因此最后一个子对象呈现在顶部(每个元素的默认 z 索引为 0)。 这与其他内置面板相同。 但是,Canvas 还支持 可以在每个子元素上设置的 Canvas.ZIndex 附加属性。 可以在代码中设置此属性,以在运行时更改元素的绘制顺序。 具有最高 Canvas.ZIndex 值的元素将最后绘制,因此,在共享相同空间或以任何方式重叠的任何其他元素上绘制。 请注意,会遵循 alpha 值(透明度),因此,即使元素重叠,如果顶部区域具有非最大 alpha 值,则重叠区域中显示的内容可能会混合。
Canvas 不对其子级进行任何大小调整。 每个元素必须指定其大小。
下面是 XAML 中的 Canvas 示例。
<Canvas Width="120" Height="120">
<Rectangle Fill="Red" Height="44" Width="44"/>
<Rectangle Fill="Blue" Height="44" Width="44" Canvas.Left="20" Canvas.Top="20"/>
<Rectangle Fill="Green" Height="44" Width="44" Canvas.Left="40" Canvas.Top="40"/>
<Rectangle Fill="Orange" Height="44" Width="44" Canvas.Left="60" Canvas.Top="60"/>
</Canvas>
结果如下所示。
使用具有自由裁量权的画布面板。 尽管在某些方案中能够精确控制 UI 中元素的位置是很方便的,但固定定位布局面板会导致 UI 的该区域不太适应整个应用窗口大小的变化。 应用窗口大小可能来自设备方向更改、拆分应用窗口、更改监视器和许多其他用户方案。
ItemsControl 面板
有几个特殊用途面板只能用作 ItemsPanel 来显示 ItemsControl 中的项。 这些是 ItemsStackPanel、ItemsWrapGrid、VirtualizingStackPanel 和 WrapGrid。 不能将这些面板用于常规 UI 布局。
获取示例代码
- WinUI 2 库示例 - 以交互式格式查看所有 XAML 控件。