Avalonia 布局的核心是容器控件通过规则划分空间,子元素依附容器规则排列,核心布局体系与 WPF 高度同源,90% 以上的逻辑可直接迁移。以下结合 Avalonia 原生语法糖简写特性,系统梳理 Grid、StackPanel、WrapPanel、DockPanel、UniformGrid 的核心特性、用法和差异,所有示例与 WPF 原版逻辑一一对应,采用最简语法糖写法,功能完全等价且代码更精简。
一、Grid:最灵活的网格布局(Avalonia 布局基石)
Grid 是 Avalonia 最核心的布局控件,通过行(RowDefinitions) 和 列(ColumnDefinitions) 将空间划分为二维网格,支持自定义尺寸、跨行列,是绝大多数 Avalonia 界面的基础容器。
Avalonia 增强:支持字符串语法糖简写,直接在 Grid 标签上通过
RowDefinitions/ColumnDefinitions属性一键声明行列规则,无需嵌套多层标签。
1. Grid 核心规则:行高 / 列宽的 3 种定义方式
Grid 的行高(Height)和列宽(Width)是其核心,支持三种核心定义方式,决定了网格空间的分配逻辑,语法糖中直接用逗号分隔即可:
| 定义方式 | 语法糖示例 | 实际含义 | 设计层面的理解 |
|---|---|---|---|
Auto |
RowDefinitions="Auto,*" |
以子元素 DesiredSize 为准 | 内容驱动布局 |
* |
RowDefinitions="2*,1*" |
在剩余空间中按比例分配 | 区域驱动布局 |
| 固定值 | RowDefinitions="100,*" |
像素级锁定 | 视觉约束 |
2. Grid 实战示例解析
(1)基础 2 行 2 列均分布局
这是 Grid 最基础的用法,未指定行高 / 列宽时,所有行 / 列按 1:1 比例均分空间,语法糖直接声明行列:
xml
<!--
Grid(网格布局)是Avalonia中最常用的布局容器控件之一
通过 RowDefinitions(行定义)、ColumnDefinitions(列定义)将整体区域切分为网格行列
语法糖写法:RowDefinitions="*,*" 等价于手动创建两行均分高度;ColumnDefinitions="*,*" 两列均分宽度
行列索引【从0开始计数】
-->
<Grid RowDefinitions="*,*" ColumnDefinitions="*,*">
<!-- 第0行,第0列 | 红色背景边框 -->
<Border Grid.Row="0" Grid.Column="0" Background="Red" />
<!-- 第0行,第1列 | 黄色背景边框 -->
<Border Grid.Row="0" Grid.Column="1" Background="Yellow" />
<!-- 第1行,第0列 | 蓝色背景边框 -->
<Border Grid.Row="1" Grid.Column="0" Background="Blue" />
<!-- 第1行,第1列 | 绿色背景边框 -->
<Border Grid.Row="1" Grid.Column="1" Background="Green" />
</Grid>

效果: 4 个 Border 各占 Grid 空间的 1/4,行高、列宽均为容器的 50%。
(2)auto 行高:适配内容尺寸
将第一行高度设为auto,行高会跟随内部子元素的高度变化(如子元素是 100 高的按钮,行高自动为 100):
xml
<!--
Grid(网格布局)是Avalonia中最常用的布局控件之一
可以通过 RowDefinitions / ColumnDefinitions 语法糖将空间划分为网格状
-->
<Grid RowDefinitions="Auto,*" ColumnDefinitions="*,*">
<!-- 定义Grid的行集合:这里定义了2行 -->
<!-- 重点改了!第一行高度设为auto -->
<!-- 第二行没设Height,默认*比例 -->
<!-- 第一行第一列(索引从0开始)放置红色背景的Border控件 -->
<Border Grid.Row="0" Grid.Column="0" Background="Red" />
<!-- 第一行第二列放置黄色背景的Border控件 -->
<Border Grid.Row="0" Grid.Column="1" Background="Yellow" />
<!-- 第二行第一列放置蓝色背景的Border控件 -->
<Border Grid.Row="1" Grid.Column="0" Background="Blue" />
<!-- 第二行第二列放置绿色背景的Border控件 -->
<Border Grid.Row="1" Grid.Column="1" Background="Green" />
</Grid>
效果: 第一行高度由内部 Border 的高度决定(无固定尺寸时仅占内容最小高度),第二行占满剩余所有空间。
添加一个按钮高度是100 ,那么第一行默认为100
xml
<!-- 网格布局:2行2列
RowDefinitions="Auto,*"
Auto:第0行高度自适应内部最大控件尺寸
*:第1行占用窗口剩余全部高度
ColumnDefinitions="*,*"
两列均分网格总宽度 -->
<Grid RowDefinitions="Auto,*" ColumnDefinitions="*,*">
<!-- 第0行第0列 红色底层背景 -->
<Border Grid.Row="0" Grid.Column="0" Background="Red" />
<!-- 同一单元格叠加按钮,高度100px,决定第一行Auto高度 -->
<Button Grid.Row="0" Grid.Column="0" Height="100" Content="测试按钮"/>
<!-- 第0行第1列 黄色背景 -->
<Border Grid.Row="0" Grid.Column="1" Background="Yellow" />
<!-- 第1行第0列 蓝色背景 -->
<Border Grid.Row="1" Grid.Column="0" Background="Blue" />
<!-- 第1行第1列 绿色背景 -->
<Border Grid.Row="1" Grid.Column="1" Background="Green" />
</Grid>

(3)固定行高:精准控制尺寸
将第一行高度设为固定值100,行高不再随内容或容器变化,始终保持 100 像素:
xml
<!--
Grid(网格布局)是Avalonia中最常用的布局控件之一
可以通过 RowDefinitions / ColumnDefinitions 语法糖将空间划分为网格状
-->
<Grid RowDefinitions="100,*" ColumnDefinitions="*,*">
<!-- 定义Grid的行集合:这里定义了2行 -->
<!-- 重点改了!第一行高度设为100 -->
<!-- 第二行没设Height,默认*比例 -->
<!-- 第一行第一列(索引从0开始)放置红色背景的Border控件 -->
<Border Grid.Row="0" Grid.Column="0" Background="Red" />
<!-- 第一行第二列放置黄色背景的Border控件 -->
<Border Grid.Row="0" Grid.Column="1" Background="Yellow" />
<!-- 第二行第一列放置蓝色背景的Border控件 -->
<Border Grid.Row="1" Grid.Column="0" Background="Blue" />
<!-- 第二行第二列放置绿色背景的Border控件 -->
<Border Grid.Row="1" Grid.Column="1" Background="Green" />
</Grid>

(4)比例行高(n*):按比例分配空间
将第一行高度设为2*,第二行默认1*,两行按 2:1 的比例瓜分 Grid 的总高度:
xml
<!--
Grid(网格布局)是Avalonia中最常用的布局控件之一
可以通过 RowDefinitions / ColumnDefinitions 语法糖将空间划分为网格状
-->
<Grid RowDefinitions="2*,*" ColumnDefinitions="*,*">
<!-- 定义Grid的行集合:这里定义了2行 -->
<!-- 重点改了!第一行高度设为2* -->
<!-- 第二行没设Height,默认*比例 -->
<!-- 第一行第一列(索引从0开始)放置红色背景的Border控件 -->
<Border Grid.Row="0" Grid.Column="0" Background="Red" />
<!-- 第一行第二列放置黄色背景的Border控件 -->
<Border Grid.Row="0" Grid.Column="1" Background="Yellow" />
<!-- 第二行第一列放置蓝色背景的Border控件 -->
<Border Grid.Row="1" Grid.Column="0" Background="Blue" />
<!-- 第二行第二列放置绿色背景的Border控件 -->
<Border Grid.Row="1" Grid.Column="1" Background="Green" />
</Grid>

(5)跨行列布局:RowSpan/ColumnSpan
通过RowSpan(跨行)、ColumnSpan(跨列),可让子元素占据多个网格区域,配合语法糖行列定义使用:
跨2列
xml
<!--
Grid(网格布局):Avalonia中最核心、最灵活的布局控件
核心能力:通过RowDefinitions(行集合)和ColumnDefinitions(列集合)语法糖将容器划分为网格状区域
每个控件可通过Grid.Row/Grid.Column指定放置的网格位置,还能通过RowSpan/ColumnSpan跨行列
-->
<Grid RowDefinitions="*,*" ColumnDefinitions="*,*">
<!-- 2行2列网格,行列1:1均分空间 -->
<!-- Grid.ColumnSpan="2" 横向跨两列 -->
<Border Grid.ColumnSpan="2" Background="Red" />
</Grid>

跨2行
xml
<Grid RowDefinitions="*,*" ColumnDefinitions="*,*">
<!-- 2行2列网格,行列1:1均分空间 -->
<!-- Grid.RowSpan="2" 纵向跨两行 -->
<Border Grid.RowSpan="2" Background="Red" />
</Grid>

3. Grid 注意事项
- 行 / 列索引从 0 开始,子元素未指定
Grid.Row/Grid.Column时,默认放在第 0 行第 0 列; auto行 / 列会优先占用空间,剩余空间才会分配给*行 / 列;- 跨行列元素会覆盖对应网格区域,需注意布局层级与重叠问题;
- 语法糖简写适合简单行列规则,如需设置
MinWidth/MaxWidth等复杂属性,仍需使用完整标签写法。
二、StackPanel:线性堆栈布局(简单高效的单行 / 列排列)
StackPanel 是 Avalonia 中最简洁的线性布局控件,子元素沿Orientation指定的方向(垂直 / 水平)依次堆叠,适合固定数量的单行 / 列元素排列。
Avalonia 增强:原生支持
Spacing语法糖属性,可统一设置子元素间距,无需逐个写 Margin。
1. StackPanel 核心特性
- 排列方向:
Orientation="Vertical"(默认,垂直堆叠)/Orientation="Horizontal"(水平堆叠); - 超出处理:子元素总尺寸超出容器时,无滚动条,超出部分直接隐藏;
- 尺寸适配:若父容器行高为
*(非 auto),StackPanel 会在容器中居中显示; - 语法糖增强:
Spacing属性一键设置子元素间距,替代逐个元素写 Margin。
2. StackPanel 实战示例
(1)垂直堆叠:7 个固定尺寸按钮
xml
<!-- Grid:两行两列布局
RowDefinitions="Auto,*" 首行自适应内容,第二行占用剩余高度
ColumnDefinitions="*,*" 两列平分宽度 -->
<Grid RowDefinitions="Auto,*" ColumnDefinitions="*,*">
<!-- StackPanel 默认垂直布局,Spacing 设置子控件间距 -->
<StackPanel Spacing="2">
<Button Width="100" Height="40" >按钮1</Button>
<Button Width="100" Height="40" >按钮2</Button>
<Button Width="100" Height="40" >按钮3</Button>
<Button Width="100" Height="40" >按钮4</Button>
<Button Width="100" Height="40" >按钮5</Button>
<Button Width="100" Height="40" >按钮6</Button>
<Button Width="100" Height="40" >按钮7</Button>
</StackPanel>
</Grid>

(2)水平堆叠:7 个固定尺寸按钮
xml
<!-- Grid:2行2列布局,首行自适应高度,次行占用剩余高度;两列平分宽度 -->
<Grid RowDefinitions="Auto,*" ColumnDefinitions="*,*">
<!-- 第0行0列(按钮所在区域)浅蓝色 -->
<Border Background="#cce5ff"/>
<!-- 第0行1列(右上空白区域)浅绿色 -->
<Border Grid.Column="1" Background="#d4edda"/>
<!-- 第1行0列(左下空白区域)浅黄色 -->
<Border Grid.Row="1" Background="#fff3cd"/>
<!-- 第1行1列(右下空白区域)浅粉色 -->
<Border Grid.Row="1" Grid.Column="1" Background="#f8d7da"/>
<!-- StackPanel 水平排列子控件,Spacing 设置元素间距 -->
<StackPanel Orientation="Horizontal" Spacing="2">
<Button Width="100" Height="40" >按钮1</Button>
<Button Width="100" Height="40" >按钮2</Button>
<Button Width="100" Height="40" >按钮3</Button>
<Button Width="100" Height="40" >按钮4</Button>
<Button Width="100" Height="40" >按钮5</Button>
<Button Width="100" Height="40" >按钮6</Button>
<Button Width="100" Height="40" >按钮7</Button>
</StackPanel>
</Grid>

3. 关键优化:去掉 auto 行高实现居中
若将 Grid 第 0 行的Height="auto"改为默认*,StackPanel 会在占满行高的 Grid 中水平居中显示:
xml
<Grid RowDefinitions="*,*" ColumnDefinitions="*,*">
<!-- 四个分区底色,区分4个象限 -->
<Border Background="#87CEEB"/>
<Border Grid.Column="1" Background="#90EE90"/>
<Border Grid.Row="1" Background="#FFE488"/>
<Border Grid.Row="1" Grid.Column="1" Background="#FFB6C1"/>
<!-- 控件默认位于 第0行第0列(左上蓝色区域) -->
<StackPanel Orientation="Horizontal" Spacing="2">
<Button Width="100" Height="40" >按钮1</Button>
<Button Width="100" Height="40" >按钮2</Button>
<Button Width="100" Height="40" >按钮3</Button>
<Button Width="100" Height="40" >按钮4</Button>
<Button Width="100" Height="40" >按钮5</Button>
<Button Width="100" Height="40" >按钮6</Button>
<Button Width="100" Height="40" >按钮7</Button>
</StackPanel>
</Grid>

三、WrapPanel:自动换行布局(StackPanel 增强版)
WrapPanel 继承了 StackPanel 的线性排列逻辑,但解决了 "超出隐藏" 的问题 ------ 子元素超出容器宽度(水平)/ 高度(垂直)时,会自动换行 / 换列,适合动态数量的元素布局(如标签云、按钮列表)。
Avalonia 增强:同样支持
Spacing语法糖统一设置子元素间距。
1. StackPanel vs WrapPanel 对比示例
| 特性 | StackPanel | WrapPanel |
|---|---|---|
| 超出处理 | 隐藏超出部分 | 自动换行 / 列 |
| 空间利用率 | 低(仅沿单方向排列) | 高(自动填充多行 / 列) |
| 适用场景 | 固定数量、单行 / 列元素 | 动态数量、需自适应换行元素 |
2. 对比示例代码
xml
<Grid RowDefinitions="*,*" ColumnDefinitions="*,*">
<!-- 四区域底色,直观区分4个象限范围 -->
<Border Background="#cce5ff"/>
<Border Grid.Column="1" Background="#d4edda"/>
<Border Grid.Row="1" Background="#fff3cd"/>
<Border Grid.Row="1" Grid.Column="1" Background="#f8d7da"/>
<!-- 左上(0行0列):水平StackPanel
元素单向水平排列,空间不足时内容直接截断隐藏;原生支持Spacing设置元素间距 -->
<StackPanel Orientation="Horizontal" Spacing="2">
<Button Width="100" Height="40" >按钮1</Button>
<Button Width="100" Height="40" >按钮2</Button>
<Button Width="100" Height="40" >按钮3</Button>
<Button Width="100" Height="40" >按钮4</Button>
<Button Width="100" Height="40" >按钮5</Button>
<Button Width="100" Height="40" >按钮6</Button>
<Button Width="100" Height="40" >按钮7</Button>
</StackPanel>
<!-- 左下(1行0列):WrapPanel
元素横向排布,容器宽度不够时自动换行;当前Avalonia版本不支持Spacing,使用Margin模拟间距 -->
<WrapPanel Grid.Row="1">
<Button Width="100" Height="40" Margin="2">按钮1</Button>
<Button Width="100" Height="40" Margin="2">按钮2</Button>
<Button Width="100" Height="40" Margin="2">按钮3</Button>
<Button Width="100" Height="40" Margin="2">按钮4</Button>
<Button Width="100" Height="40" Margin="2">按钮5</Button>
<Button Width="100" Height="40" Margin="2">按钮6</Button>
<Button Width="100" Height="40" Margin="2">按钮7</Button>
</WrapPanel>
</Grid>

效果:StackPanel 的按钮超出容器宽度后隐藏,而 WrapPanel 会自动换行,所有按钮都能显示。
四、DockPanel:停靠布局(窗体框架首选)
DockPanel 让子元素沿Top/Bottom/Left/Right方向停靠,剩余空间由最后一个子元素填充(可通过LastChildFill关闭),是搭建窗体框架(顶部导航、底部状态栏、侧边栏)的首选。
语法说明:DockPanel 核心语法与 WPF 完全一致,无额外差异,外层 Grid 采用语法糖简写。
1. DockPanel 核心规则
- 停靠顺序决定布局:先停靠的元素优先占用空间,后停靠的元素在剩余空间内停靠;
LastChildFill:默认True,最后一个子元素填充剩余空间;设为False则仅显示手动停靠的元素;- 正确停靠逻辑:先停靠
Top/Bottom(纵向),再停靠Left/Right(横向),避免空间挤压。
2. DockPanel 实战示例
xml
<Grid RowDefinitions="Auto,Auto,Auto,Auto">
<!-- 4行网格,全部Auto自适应高度 -->
<!-- 各行底色区分区域 -->
<Border Background="#cce5ff"/>
<Border Grid.Row="1" Background="#d4edda"/>
<Border Grid.Row="2" Background="#fff3cd"/>
<Border Grid.Row="3" Background="#f8d7da"/>
<!-- 第0行 蓝色区域:默认DockPanel,LastChildFill=True,无指定Dock默认向左停靠,最后控件自动填充剩余宽度 -->
<DockPanel >
<Button Width="100" Height="40" >按钮1</Button>
<Button Width="100" Height="40" >按钮2</Button>
<Button Width="100" Height="40" >按钮3</Button>
<Button Width="100" Height="40" >按钮4</Button>
</DockPanel>
<!-- 第1行 绿色区域:关闭LastChildFill,所有控件保持自身尺寸,不会自动填充空白 -->
<DockPanel Grid.Row="1" LastChildFill="False">
<Button Width="100" Height="40" >按钮1</Button>
<Button Width="100" Height="40" >按钮2</Button>
<Button Width="100" Height="40" >按钮3</Button>
<Button Width="100" Height="40" >按钮4</Button>
</DockPanel>
<!-- 第2行 黄色区域:停靠顺序错误示范,横向纵向交错停靠,空间互相挤压,布局异常 -->
<DockPanel Grid.Row="2" LastChildFill="False">
<Button Width="100" Height="40" DockPanel.Dock="Left" >按钮1</Button>
<Button Width="100" Height="40" DockPanel.Dock="Top" >按钮2</Button>
<Button Width="100" Height="40" DockPanel.Dock="Right" >按钮3</Button>
<Button Width="100" Height="40" DockPanel.Dock="Bottom" >按钮4</Button>
</DockPanel>
<!-- 第3行 粉色区域:标准停靠顺序,先纵向Top/Bottom,后横向Left/Right,布局规整无挤压 -->
<DockPanel Grid.Row="3" LastChildFill="False" Background="#F0F0F0">
<Button Width="100" Height="40" DockPanel.Dock="Top" Content="按钮2(上)" HorizontalAlignment="Center"/>
<Button Width="100" Height="40" DockPanel.Dock="Bottom" Content="按钮4(下)" HorizontalAlignment="Center"/>
<Button Width="100" Height="100" DockPanel.Dock="Left" Content="按钮1(左)" VerticalAlignment="Center"/>
<Button Width="100" Height="100" DockPanel.Dock="Right" Content="按钮3(右)" VerticalAlignment="Center"/>
</DockPanel>
</Grid>

效果:示例 4 的布局规整无挤压,是 DockPanel 的标准用法;示例 3 因停靠顺序错误,元素空间被严重挤压,显示异常。
五、UniformGrid:均匀网格布局(等分空间神器)
UniformGrid 是 Grid 的简化版,无需手动定义行 / 列尺寸,自动将空间平均分配给所有单元格,所有单元格尺寸完全相同,适合 "等分空间" 场景(如计算器按钮、九宫格、键盘按键)。
1. UniformGrid 核心属性
Columns:指定列数;Rows:指定行数;- 特性:子元素自动填充单元格,数量不足时剩余单元格为空,数量过多时自动换行 / 列。
2. UniformGrid 实战示例
xml
<Grid>
<!-- UniformGrid:均分网格,空间自动等分,无需手动定义行列尺寸 -->
<!-- Columns列数4,Rows行数3,合计12单元格;9个按钮填充前9格,剩余单元格留白 -->
<UniformGrid Columns="4" Rows="3">
<Button Content="按钮1" Background="#cce5ff"/>
<Button Content="按钮2" Background="#d4edda"/>
<Button Content="按钮3" Background="#fff3cd"/>
<Button Content="按钮4" Background="#f8d7da"/>
<Button Content="按钮5" Background="#e2e3e5"/>
<Button Content="按钮6" Background="#d1ecf1"/>
<Button Content="按钮7" Background="#ffeeba"/>
<Button Content="按钮8" Background="#c3e6cb"/>
<Button Content="按钮9" Background="#bee5eb"/>
<!-- 第10、11、12单元格无控件,空白 -->
</UniformGrid>
</Grid>

效果: 4 列 3 行共 12 个单元格,9 个按钮填充前 9 个,每个单元格尺寸 = 容器宽度 / 4、容器高度 / 3,完全均分。
六、核心布局控件选型指南
| 控件 | 核心优势 | 核心劣势 | 适用场景 |
|---|---|---|---|
| Grid | 灵活、支持语法糖简写、跨行列 | 复杂场景需完整写法 | 复杂界面(窗体、表单、多模块布局) |
| StackPanel | 简单、线性排列、支持Spacing | 超出隐藏、无自动换行 | 固定数量单行 / 列元素(导航栏、列表项) |
| WrapPanel | 自动换行、适配动态元素、支持Spacing | 无法精准控制位置 | 动态数量元素(标签云、按钮列表) |
| DockPanel | 按方向停靠、布局规整 | 依赖停靠顺序、易挤压 | 窗体框架(顶部导航、底部状态栏、侧边栏) |
| UniformGrid | 均分空间、配置简单 | 需引入命名空间、无法自定义单元格尺寸 | 等分布局(计算器、九宫格、键盘按键) |
七、总结
- Avalonia 布局的核心是 "容器规则 + 子元素适配",掌握以下要点可快速搭建高质量界面;
- 优先用 Grid 作为根容器,配合语法糖简写大幅精简代码,嵌套其他布局控件实现复杂布局;
- StackPanel 适合简单线性排列,WrapPanel 适配动态元素换行,两者优先使用
Spacing统一设置间距; - DockPanel 搭建窗体框架时,务必遵循 "先纵向(Top/Bottom)、后横向(Left/Right)" 的停靠顺序;
- UniformGrid 是等分空间的最优解,无需手动计算比例,注意引入 Primitives 命名空间;
- 行 / 列尺寸优先用*(比例)和auto(自适应),固定值仅用于精准控制的场景。
通过灵活组合这些布局控件,可兼顾 Avalonia 界面的 "自适应" 与 "美观性",满足从简单按钮列表到复杂业务窗体的所有布局需求。

👋 关注我!持续分享 C# 实战技巧、代码示例 & 工具网站 & 技术干货
- 获取示例代码,轻松上手!