跨平台WPF框架Avalonia教程 四
布局
面板(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
,布局过程完成。
Alignment、Margin 和 Padding
Avalonia 控件暴露了用于精确定位子元素的几个属性。本章节讨论了四个最重要的属性:HorizontalAlignment
、Margin
、Padding
和VerticalAlignment
。理解这些属性的效果很重要,因为它们是控制元素在Avalonia应用程序中的位置的基础。
元素定位
Avalonia定位元素有许多使用方式。然而,实现理想的布局不仅仅是选择正确的Panel
元素,精确控制定位还需要理解HorizontalAlignment
、Margin
、Padding
和VerticalAlignment
属性。
下图展示了一个使用了多个定位属性的布局方案。
乍一看,本图中的Button
元素可能是随机放置的。然而,它们的位置实际上是通过组合使用边距(margin)、对齐(alignment)和填充(padding)来精确控制的。
以下示例描述了如何创建上图中的布局。一个Border
元素封装了一个父元素StackPanel
,Padding
值为15个设备独立像素。这就说明了围绕子StackPanel
的狭窄的LightBlue
部分。StackPanel
的子元素用于说明本章节中详细介绍的每个不同的定位属性。三个Button
元素用于演示Margin
和HorizontalAlignment
属性。
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="AvaloniaApplication2.MainWindow"
Title="AvaloniaApplication2">
<Border Background="LightBlue"
BorderBrush="Black"
BorderThickness="2"
Padding="15">
<StackPanel Background="White"
HorizontalAlignment="Center"
VerticalAlignment="Top">
<TextBlock Margin="5,0"
FontSize="18"
HorizontalAlignment="Center">
Alignment, Margin and Padding Sample
</TextBlock>
<Button HorizontalAlignment="Left" Margin="20">Button 1</Button>
<Button HorizontalAlignment="Right" Margin="10">Button 2</Button>
<Button HorizontalAlignment="Stretch">Button 3</Button>
</StackPanel>
</Border>
</Window>
下图提供了上述示例中使用的各种定位属性的全貌图。本章节的后续部分会更详细地描述如何使用每个定位属性。
理解Alignment属性
HorizontalAlignment
和VerticalAlignment
属性描述了一个子元素应该如何在父元素分配的布局空间内定位。通过一起使用这些属性,你可以精确地定位子元素。例如,DockPanel
的子元素可以指定四种不同的水平对齐方式。Left
、Right
、Center
或者Stretch
(拉伸)以填补可用空间。类似的值也可用于垂直定位。
元素上明确设置的Height
和Width
属性的优先级高于Stretch
属性。如果明确设置了Height
和Width
,再将HorizontalAlignment
设置为Stretch
,这样会忽略Stretch
属性。
HorizontalAlignment属性
HorizontalAlignment
属性声明了要应用于子元素的水平对齐特性。下表列出了HorizontalAlignment
属性的可选值。
成员 | 描述 |
---|---|
Left | 子元素与父元素分配的布局空间的左侧对齐。 |
Center | 子元素与父元素分配的布局空间的中心对齐。 |
Right | 子元素与父元素分配的布局空间的右侧对齐。 |
Stretch (默认) | 子元素被拉伸以填充父元素分配的布局空间。明确的Width 和Height 值优先级更高。 |
下面的示例展示了如何将HorizontalAlignment
属性应用于Button
元素。为了更好地说明各种渲染行为,每种特性值的效果都被展示了出来。
<Button HorizontalAlignment="Left">Button 1 (Left)</Button>
<Button HorizontalAlignment="Right">Button 2 (Right)</Button>
<Button HorizontalAlignment="Center">Button 3 (Center)</Button>
<Button HorizontalAlignment="Stretch">Button 4 (Stretch)</Button>
前面的代码生成了与下图类似的布局。每种HorizontalAlignment
值的定位效果在图中可见。
VerticalAlignment属性
VerticalAlignment
属性声明了要应用于子元素的垂直对齐特性。下表列出了VerticalAlignment
属性的可选值。
成员 | 描述 |
---|---|
Top | 子元素与父元素分配的布局空间的顶部对齐。 |
Center | 子元素与父元素分配的布局空间的中心对齐。 |
Bottom | 子元素与父元素分配的布局空间的底部对齐。 |
Stretch (默认) | 子元素被拉伸以填充父元素分配的布局空间。明确的Width 和Height 值优先级更高。 |
下面的示例展示了如何将VerticalAlignment
属性应用于Button
元素。为了更好地说明各种渲染行为,每种特性值的效果都被展示了出来。在本示例中,使用具有可见网格线的Grid
元素作为父元素,以更好地说明每种属性值的布局行为。
<Border Background="LightBlue" BorderBrush="Black" BorderThickness="2" Padding="15">
<Grid Background="White" ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0"
FontSize="18"
HorizontalAlignment="Center">
VerticalAlignment Sample
</TextBlock>
<Button Grid.Row="1" Grid.Column="0" VerticalAlignment="Top">Button 1 (Top)</Button>
<Button Grid.Row="2" Grid.Column="0" VerticalAlignment="Bottom">Button 2 (Bottom)</Button>
<Button Grid.Row="3" Grid.Column="0" VerticalAlignment="Center">Button 3 (Center)</Button>
<Button Grid.Row="4" Grid.Column="0" VerticalAlignment="Stretch">Button 4 (Stretch)</Button>
</Grid>
</Border>
前面的代码生成了与下图类似的布局。每种VerticalAlignment
值的定位效果在图中可见。
理解Margin属性
Margin
属性描述了元素与其子元素或同级元素之间的距离。Margin
值可以是相同的,通过使用像Margin="20"
的语法,元素将使用相同的20个设备独立像素的Margin
。Margin
值也可以是四个不同的值,每个值描述了应用于左、上、右和下的不同边距(按顺序),如Margin="0,10,5,25"
。正确使用Margin
属性可以非常精确地控制元素的渲染位置及其相邻元素和子元素的渲染位置。
非零的边距应用在元素的Bounds
之外的空间。
下面的示例展示了如何在一组Button
元素周围应用相同的边距。这些Button
元素的间距是均匀的,每个方向都有10像素的边距缓冲。
<Button Margin="10">Button 7</Button>
<Button Margin="10">Button 8</Button>
<Button Margin="10">Button 9</Button>
在许多情况下,统一的边距是不合适的。在这些情况下,可以应用非统一间距。以下示例展示了如何将非统一边距应用于子元素。边距按该顺序描述:左、上、右、下。
<Button Margin="0,10,0,10">Button 1</Button>
<Button Margin="0,10,0,10">Button 2</Button>
<Button Margin="0,10,0,10">Button 3</Button>
理解Padding属性
Padding
在大多数方面与Margin
相似。Padding
属性仅暴露在少数类上,主要是为了方便。Border
、TemplatedControl
、和TextBlock
是暴露了Padding
属性的类的范例。Padding
属性通过指定的Thickness
值扩大了子元素的有效尺寸。
以下示例展示了如何将Padding
应用于父Border
元素。
<Border Background="LightBlue"
BorderBrush="Black"
BorderThickness="2"
CornerRadius="45"
Padding="25">
在应用程序中使用Alignment、Margin和Padding
HorizontalAlignment
、Margin
、Padding
和VerticalAlignment
提供创建复杂UI所需的定位控制。您可以使用每个属性的效果来改变子元素的位置,从而实现灵活地创建动态应用程序和提升用户体验。
下面的示例演示了本章节中详细介绍的每个概念。在本章节第一个示例的基础上,这个示例添加了一个Grid
元素作为第一个示例中Border
的子元素。Padding
应用于父Border
元素。Grid
用于三个子StackPanel
元素之间划分空间。Button
元素再次被用来展示Margin
和HorizontalAlignment
的各种效果。TextBlock
元素被添加到每个ColumnDefinition
中,以更好地定义应用于每一列中Button
元素的各种属性。
<Border Background="LightBlue"
BorderBrush="Black"
BorderThickness="2"
CornerRadius="45"
Padding="25">
<Grid Background="White" ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Grid.Row="0"
HorizontalAlignment="Left"
Name="StackPanel1"
VerticalAlignment="Top">
<TextBlock FontSize="18" HorizontalAlignment="Center" Margin="0,0,0,15">StackPanel1</TextBlock>
<Button Margin="0,10,0,10">Button 1</Button>
<Button Margin="0,10,0,10">Button 2</Button>
<Button Margin="0,10,0,10">Button 3</Button>
<TextBlock>ColumnDefinition.Width="Auto"</TextBlock>
<TextBlock>StackPanel.HorizontalAlignment="Left"</TextBlock>
<TextBlock>StackPanel.VerticalAlignment="Top"</TextBlock>
<TextBlock>StackPanel.Orientation="Vertical"</TextBlock>
<TextBlock>Button.Margin="0,10,0,10"</TextBlock>
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="0"
HorizontalAlignment="Stretch"
Name="StackPanel2"
VerticalAlignment="Top"
Orientation="Vertical">
<TextBlock FontSize="18" HorizontalAlignment="Center" Margin="0,0,0,15">StackPanel2</TextBlock>
<Button Margin="10,0,10,0">Button 4</Button>
<Button Margin="10,0,10,0">Button 5</Button>
<Button Margin="10,0,10,0">Button 6</Button>
<TextBlock HorizontalAlignment="Center">ColumnDefinition.Width="*"</TextBlock>
<TextBlock HorizontalAlignment="Center">StackPanel.HorizontalAlignment="Stretch"</TextBlock>
<TextBlock HorizontalAlignment="Center">StackPanel.VerticalAlignment="Top"</TextBlock>
<TextBlock HorizontalAlignment="Center">StackPanel.Orientation="Horizontal"</TextBlock>
<TextBlock HorizontalAlignment="Center">Button.Margin="10,0,10,0"</TextBlock>
</StackPanel>
<StackPanel Grid.Column="2" Grid.Row="0"
HorizontalAlignment="Left"
Name="StackPanel3"
VerticalAlignment="Top">
<TextBlock FontSize="18" HorizontalAlignment="Center" Margin="0,0,0,15">StackPanel3</TextBlock>
<Button Margin="10">Button 7</Button>
<Button Margin="10">Button 8</Button>
<Button Margin="10">Button 9</Button>
<TextBlock>ColumnDefinition.Width="Auto"</TextBlock>
<TextBlock>StackPanel.HorizontalAlignment="Left"</TextBlock>
<TextBlock>StackPanel.VerticalAlignment="Top"</TextBlock>
<TextBlock>StackPanel.Orientation="Vertical"</TextBlock>
<TextBlock>Button.Margin="10"</TextBlock>
</StackPanel>
</Grid>
</Border>
编译时,前面的应用程序生成的UI与下图类似。各种属性值的影响在元素之间的间距中很明显,每列元素的重要属性值展示在TextBlock
元素中。
Panels Overview
Panel
元素是控制元素的呈现方式的组件,包括元素的大小和尺寸、位置以及子内容的排列。Avalonia UI 提供了许多预定义的 Panel
元素,同时也支持构建自定义的 Panel
元素。
Panel 类
Panel
是所有在 Avalonia 中提供布局支持的元素的基类。派生的 Panel
元素用于在 XAML 和代码中定位和排列元素。
Avalonia 包含一套全面的派生面板实现,支持许多复杂的布局。这些派生类公开了属性和方法,以支持大多数标准的 UI 场景。无法找到满足需求的子元素排列行为的开发人员可以通过重写 ArrangeOverride
和 MeasureOverride
方法来创建新的布局。有关自定义布局行为的更多信息,请参阅 Create a Custom Panel。
Panel 公共成员
所有 Panel
元素支持 Control
定义的基本大小和定位属性,包括 Height
、Width
、HorizontalAlignment
、VerticalAlignment
和 Margin
。有关由 Control
定义的定位属性的更多信息,请参阅 Alignment、Margin 和 Padding。
Panel
还公开了其他一些属性,在理解和使用布局方面非常重要。Background
属性用于使用 Brush
填充派生面板元素边界之间的区域。Children
表示 Panel
所包含的子元素集合。
附加属性
派生的面板元素广泛使用附加属性。附加属性是一种特殊形式的依赖属性,它没有常规的公共语言运行时 (CLR) 属性 "包装器"。附加属性在 XAML 中有一种特殊的语法,后面的示例中会看到。
附加属性的一个用途是允许子元素存储父元素实际定义的属性的唯一值。这个功能的一个应用是让子元素告诉父元素它们希望在 UI 中如何呈现,这对应用程序布局非常有用。
用户界面面板
Avalonia 中有几个优化支持 UI 场景的面板类:Panel
、Canvas
、DockPanel
、Grid
、StackPanel
、WrapPanel
和 RelativePanel
。这些面板元素易于使用,足够灵活且可扩展,适用于大多数应用程序。
Canvas
Canvas
元素允许按绝对 x- 和 y- 坐标定位内容。元素可以绘制在唯一位置;或者,如果元素占据相同的坐标,则在标记中出现的顺序决定元素的绘制顺序。
Canvas
提供了最灵活的布局支持。Height
和 Width
属性用于定义画布的区域,其中的元素被赋予相对于父 Canvas
区域的绝对坐标。四个附加属性 Canvas.Left
、Canvas.Top
、Canvas.Right
和 Canvas.Bottom
允许精确地控制对象在 Canvas
内的位置,从而使开发人员可以精确定位和排列元素在屏幕上的位置。
ClipToBounds 在 Canvas 中
Canvas
可以将子元素定位在屏幕上的任何位置,甚至在超出其自定义的 Height
和 Width
的坐标。此外,Canvas
不受其子元素大小的影响。因此,子元素有可能覆盖位于父 Canvas
限界矩形之外的其他元素。Canvas
的默认行为是允许子元素绘制在父 Canvas
限界之外。如果不希望出现这种情况,可以将 ClipToBounds
属性设置为 true
## RelativePanel
定义和使用 Canvas
使用 XAML 或代码可以简单地实例化一个 Canvas
。下面的示例演示了如何使用 Canvas
来绝对定位内容。该代码生成了三个大小为 100 像素的正方形。第一个正方形为红色,其左上角的 (x, y) 位置被指定为 (0, 0)。第二个正方形为绿色,其左上角位置为 (100, 100),刚好在第一个正方形的右下方。第三个正方形为蓝色,其左上角位置为 (50, 50),因此覆盖了第一个正方形的右下象限和第二个正方形的左上象限。由于第三个正方形是最后布局的,它出现在其他两个正方形的上方,即重叠部分采用第三个正方形的颜色。
- XAML
- C#
<Canvas Height="400" Width="400">
<Canvas Height="100" Width="100" Top="0" Left="0" Background="Red"/>
<Canvas Height="100" Width="100" Top="100" Left="100" Background="Green"/>
<Canvas Height="100" Width="100" Top="50" Left="50" Background="Blue"/>
</Canvas>
DockPanel
DockPanel
元素使用附加属性 DockPanel.Dock
来设置子内容元素在容器边缘的位置。当 DockPanel.Dock
设置为 Top
或 Bottom
时,它会将子元素放置在彼此的上方或下方。当 DockPanel.Dock
设置为 Left
或 Right
时,它会将子元素放置在彼此的左侧或右侧。LastChildFill
属性决定了最后一个作为 DockPanel
子元素添加的元素的位置。
你可以使用 DockPanel
来定位一组相关的控件,例如一组按钮。或者,你可以使用它来创建一个“分栏式”的用户界面。
自适应大小
如果没有指定 DockPanel
的 Height
和 Width
属性,它的大小将根据其内容来确定。大小可以根据其子元素的大小进行增长或减小。然而,当指定了这些属性并且没有足够的空间来容纳下一个指定的子元素时,DockPanel
不会显示该子元素或随后的子元素,并且不会对随后的子元素进行测量。
LastChildFill 属性
默认情况下,DockPanel
元素的最后一个子元素将“填充”剩余的未分配空间。如果不希望出现这种情况,可以将 LastChildFill
属性设置为 false
。
定义和使用 DockPanel
下面的示例演示了如何使用 DockPanel
来划分空间。五个 Border
元素被添加为 DockPanel
的子元素。每个元素使用 DockPanel
的不同定位属性来划分空间。最后一个元素将“填充”剩余的未分配空间。
- XAML
- C#
<DockPanel LastChildFill="True">
<Border Height="25" Background="SkyBlue" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Top">
<TextBlock Foreground="Black">Dock = "Top"</TextBlock>
</Border>
<Border Height="25" Background="SkyBlue" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Top">
<TextBlock Foreground="Black">Dock = "Top"</TextBlock>
</Border>
<Border Height="25" Background="LemonChiffon" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Bottom">
<TextBlock Foreground="Black">Dock = "Bottom"</TextBlock>
</Border>
<Border Width="200" Background="PaleGreen" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Left">
<TextBlock Foreground="Black">Dock = "Left"</TextBlock>
</Border>
<Border Background="White" BorderBrush="Black" BorderThickness="1">
<TextBlock Foreground="Black">This content will "Fill" the remaining space</TextBlock>
</Border>
</DockPanel>
Grid
Grid
元素合并了绝对定位和表格数据控件的功能。Grid
允许您轻松地定位和样式化元素。它允许您定义灵活的行和列分组,并且甚至可以在多个 Grid
元素之间共享大小信息。
列和行的大小行为
在 Grid
中定义的列和行可以利用 Star
大小调整功能,以便按比例分配剩余空间。当在行或列的高度或宽度中选择 Star
时,该列或行将按比例获得剩余的可用空间。这与 Auto
形式不同,后者会根据列或行中内容的大小均匀分配空间。在 XAML 中,这个值表示为 *
或 2*
。在第一种情况下,行或列将获得一倍的可用空间,在第二种情况下,将获得两倍的可用空间,依此类推。通过将这种技术与 HorizontalAlignment
和 VerticalAlignment
的值设置为 Stretch
结合使用,可以按屏幕空间的百分比划分布局空间。Grid
是唯一可以以这种方式分配空间的布局面板。
定义和使用 Grid
下面的示例演示了如何构建一个类似于 Windows 开始菜单中的“运行”对话框的用户界面。
- XAML
- C#
<Grid Background="Gainsboro"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Width="425"
Height="165"
ColumnDefinitions="Auto,*,*,*,*"
RowDefinitions="Auto,Auto,*,Auto">
<Image Grid.Row="0" Grid.Column="0" Source="{Binding runicon}" />
<TextBlock Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="4"
Text="Type the name of a program, folder, document, or Internet resource, and Windows will open it for you."
TextWrapping="Wrap" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="Open:" />
<TextBox Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="5" />
<Button Grid.Row="3" Grid.Column="2" Content="OK" Margin="10,0,10,15" />
<Button Grid.Row="3" Grid.Column="3" Content="Cancel" Margin="10,0,10,15" />
<Button Grid.Row="3" Grid.Column="4" Content="Browse ..." Margin="10,0,10,15" />
</Grid>
StackPanel
StackPanel
允许您在指定的方向上“堆叠”元素。默认的堆叠方向是垂直的。Orientation
属性可用于控制内容的流向。
StackPanel 对比 DockPanel
虽然 DockPanel
也可以“堆叠”子元素,但在某些使用场景中,DockPanel
和 StackPanel
的结果并不相同。例如,在 DockPanel
中,子元素的顺序会影响它们的大小,而在 StackPanel
中则不会。这是因为 StackPanel
在堆叠方向上测量的大小是 PositiveInfinity
,而 DockPanel
仅测量可用大小。
定义和使用 StackPanel
下面的示例演示了如何使用 StackPanel
创建一组垂直定位的按钮。如果要进行水平定位,请将 Orientation
属性设置为 Horizontal
。
- XAML
- C#
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Top"
Spacing="25">
<Button Content="Button 1" />
<Button Content="Button 2" />
<Button Content="Button 3" />
</StackPanel>
WrapPanel
WrapPanel
用于按从左到右的顺序定位子元素,并在其父容器的边缘到达时将内容折行到下一行。内容可以水平或垂直方向上定位。WrapPanel
在简单的流式界面场景中非常有用。它还可以用于对其所有子元素应用统一的大小。
下面的示例演示了如何创建一个 WrapPanel
来显示 Button
控件,并在它们到达容器边缘时进行折行。
- XAML
- C#
<Border HorizontalAlignment="Left" VerticalAlignment="Top" BorderBrush="Black" BorderThickness="2">
<WrapPanel Background="LightBlue" Width="200" Height="100">
<Button Width="200">Button 1</Button>
<Button>Button 2</Button>
<Button>Button 3</Button>
<Button>Button 4</Button>
</WrapPanel>
</Border>
嵌套面板元素
Panel
元素可以相互嵌套,以创建复杂的布局。这在某些情况下非常有用,例如一个 Panel
对于 UI 的某个部分可能非常合适,但对于另一个部分可能不符合需求。
在您的应用程序中,理论上可以无限嵌套面板元素,但通常最好仅使用实际需要的面板元素来实现所需的布局。在许多情况下,由于其作为布局容器的灵活性,可以使用 Grid
元素来替代嵌套面板。这样可以通过将不必要的元素排除在布局树之外,提高应用程序的性能。
UniformGrid
UniformGrid
是一种提供统一网格布局的面板类型。这意味着它会将其子元素布局在一个网格中,该网格中的所有单元格大小相同。与标准的 Grid
不同,UniformGrid
不支持显式行和列,也不提供 Grid.Row
或 Grid.Column
附加属性。
UniformGrid
的主要用途是在需要以网格格式显示项目集合的情况下,每个项目占用相同的空间。
UniformGrid 属性
- 行和列:
UniformGrid
使用Rows
和Columns
属性来确定其子元素的布局。如果只设置其中一个属性,UniformGrid
将自动计算另一个属性,以创建适合子元素总数的网格。如果两个属性都不设置,UniformGrid
默认为 1 行 1 列的网格。
例如,如果有 12 个项目,并将 Rows
设置为 3,则 UniformGrid
将自动创建 4 列。如果将 Columns
设置为 4,则它将自动创建 3 行。
- FirstColumn:
FirstColumn
属性允许您在网格的第一行中留下一定数量的空单元格。
定义和使用 UniformGrid
下面的示例演示了如何定义和使用 UniformGrid
。该示例创建了一个 3 行 4 列的 UniformGrid
,并将 12 个矩形作为子元素添加进去。
- XAML
- C#
<UniformGrid Rows="3" Columns="4">
<Rectangle Width="50" Height="50" Fill="#330000"/>
<Rectangle Width="50" Height="50" Fill="#660000"/>
<Rectangle Width="50" Height="50" Fill="#990000"/>
<Rectangle Width="50" Height="50" Fill="#CC0000"/>
<Rectangle Width="50" Height="50" Fill="#FF0000"/>
<Rectangle Width="50" Height="50" Fill="#FF3300"/>
<Rectangle Width="50" Height="50" Fill="#FF6600"/>
<Rectangle Width="50" Height="50" Fill="#FF9900"/>
<Rectangle Width="50" Height="50" Fill="#FFCC00"/>
<Rectangle Width="50" Height="50" Fill="#FFFF00"/>
<Rectangle Width="50" Height="50" Fill="#FFFF33"/>
<Rectangle Width="50" Height="50" Fill="#FFFF66"/>
</UniformGrid>
在上面的示例中,每个 Rectangle
被自动分配到网格中的一个单元格,按照它们被添加的顺序进行分配。
原文地址:https://blog.csdn.net/XiaoWang_csdn/article/details/143833190
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!