WPF 布局的核心是容器控件通过规则划分空间,子元素依附容器规则排列。以下结合你提供的示例,系统梳理 Grid、StackPanel、WrapPanel、DockPanel、UniformGrid 的核心特性、用法和差异。
一、Grid:最灵活的网格布局(WPF 布局基石)
Grid 是 WPF 最核心的布局控件,通过行(RowDefinitions) 和 列(ColumnDefinitions) 将空间划分为二维网格,支持自定义尺寸、跨行列,是绝大多数 WPF 界面的基础容器。
1. Grid 核心规则:行高 / 列宽的 3 种定义方式
Grid 的行高(Height)和列宽(Width)是其核心,支持三种核心定义方式,决定了网格空间的分配逻辑:
| 定义方式 | 实际含义 | 设计层面的理解 |
|---|---|---|
Auto | 以子元素 DesiredSize 为准 | 内容驱动布局 |
* | 在剩余空间中按比例分配 | 区域驱动布局 |
| 固定值 | 像素级锁定 | 视觉约束 |
2. Grid 实战示例解析
(1)基础 2 行 2 列均分布局
这是 Grid 最基础的用法,未指定行高 / 列宽时,所有行 / 列按 1:1 比例均分空间:
<!--
Grid(网格布局)是WPF中最常用的布局控件之一
可以通过行(RowDefinitions)和列(ColumnDefinitions)将空间划分为网格状
-->
<Grid>
<!-- 定义Grid的行集合:这里定义了2行 -->
<Grid.RowDefinitions>
<!-- 单个行定义,未指定Height时默认均分空间(即每行占窗口高度的50%) -->
<RowDefinition />
<RowDefinition/>
</Grid.RowDefinitions>
<!-- 定义Grid的列集合:这里定义了2列 -->
<Grid.ColumnDefinitions>
<!-- 单个列定义,未指定Width时默认均分空间(即每列占窗口宽度的50%) -->
<ColumnDefinition />
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<!-- 第一行第一列(索引从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 个 Border 各占 Grid 空间的 1/4,行高、列宽均为容器的 50%。
(2)auto 行高:适配内容尺寸
将第一行高度设为auto,行高会跟随内部子元素的高度变化(如子元素是 100 高的按钮,行高自动为 100):
<!--
Grid(网格布局)是WPF中最常用的布局控件之一
可以通过行(RowDefinitions)和列(ColumnDefinitions)将空间划分为网格状
-->
<Grid>
<!-- 定义Grid的行集合:这里定义了2行 -->
<Grid.RowDefinitions>
<!-- 单个行定义,未指定Height时默认均分空间(即每行占窗口高度的50%) -->
<RowDefinition Height="auto"/>
<!-- 重点改了!第一行高度设为auto -->
<RowDefinition/>
<!-- 第二行没设Height,默认*比例 -->
</Grid.RowDefinitions>
<!-- 定义Grid的列集合:这里定义了2列 -->
<Grid.ColumnDefinitions>
<!-- 单个列定义,未指定Width时默认均分空间(即每列占窗口宽度的50%) -->
<ColumnDefinition />
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<!-- 第一行第一列(索引从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

(3)固定行高:精准控制尺寸
将第一行高度设为固定值100,行高不再随内容或容器变化,始终保持 100 像素:
<!--
Grid(网格布局)是WPF中最常用的布局控件之一
可以通过行(RowDefinitions)和列(ColumnDefinitions)将空间划分为网格状
-->
<Grid>
<!-- 定义Grid的行集合:这里定义了2行 -->
<Grid.RowDefinitions>
<!-- 单个行定义,未指定Height时默认均分空间(即每行占窗口高度的50%) -->
<RowDefinition Height="100"/>
<!-- 重点改了!第一行高度设为100 -->
<RowDefinition/>
<!-- 第二行没设Height,默认*比例 -->
</Grid.RowDefinitions>
<!-- 定义Grid的列集合:这里定义了2列 -->
<Grid.ColumnDefinitions>
<!-- 单个列定义,未指定Width时默认均分空间(即每列占窗口宽度的50%) -->
<ColumnDefinition />
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<!-- 第一行第一列(索引从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 的总高度:
<!--
Grid(网格布局)是WPF中最常用的布局控件之一
可以通过行(RowDefinitions)和列(ColumnDefinitions)将空间划分为网格状
-->
<Grid>
<!-- 定义Grid的行集合:这里定义了2行 -->
<Grid.RowDefinitions>
<!-- 单个行定义,未指定Height时默认均分空间(即每行占窗口高度的50%) -->
<RowDefinition Height="2*"/>
<!-- 重点改了!第一行高度设为2* -->
<RowDefinition/>
<!-- 第二行没设Height,默认*比例 -->
</Grid.RowDefinitions>
<!-- 定义Grid的列集合:这里定义了2列 -->
<Grid.ColumnDefinitions>
<!-- 单个列定义,未指定Width时默认均分空间(即每列占窗口宽度的50%) -->
<ColumnDefinition />
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<!-- 第一行第一列(索引从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列
<!--
Grid(网格布局):WPF中最核心、最灵活的布局控件
核心能力:通过RowDefinitions(行集合)和ColumnDefinitions(列集合)将容器划分为网格状区域
每个控件可通过Grid.Row/Grid.Column指定放置的网格位置,还能通过RowSpan/ColumnSpan跨行列
-->
<Grid>
<!-- 定义Grid的行集合:共定义2行 -->
<Grid.RowDefinitions>
<!-- RowDefinition未指定Height时,默认值为"*"(比例分配) -->
<RowDefinition/>
<!-- 第0行:高度占比1*,无显式Height则默认均分 -->
<RowDefinition/>
<!-- 第1行:高度占比1*,两行比例1:1,各占Grid高度的50% -->
</Grid.RowDefinitions>
<!-- 定义Grid的列集合:共定义2列 -->
<Grid.ColumnDefinitions>
<!-- ColumnDefinition未指定Width时,默认值为"*"(比例分配) -->
<ColumnDefinition />
<!-- 第0列:宽度占比1* -->
<ColumnDefinition/>
<!-- 第1列:宽度占比1*,两列比例1:1,各占Grid宽度的50% -->
</Grid.ColumnDefinitions>
<!-- Border控件布局说明:
1. 未指定Grid.Row,默认放置在第0行;
2. Grid.ColumnSpan="2":表示该控件跨2列显示(同时占据第0列和第1列);
3. Background="Red":设置控件背景色为红色
-->
<Border Grid.ColumnSpan="2" Background="Red" />
</Grid>

跨2行
<Grid>
<!-- 定义Grid的行集合:共定义2行 -->
<Grid.RowDefinitions>
<!-- RowDefinition未指定Height时,默认值为"*"(比例分配) -->
<RowDefinition/>
<!-- 第0行:高度占比1*,无显式Height则默认均分 -->
<RowDefinition/>
<!-- 第1行:高度占比1*,两行比例1:1,各占Grid高度的50% -->
</Grid.RowDefinitions>
<!-- 定义Grid的列集合:共定义2列 -->
<Grid.ColumnDefinitions>
<!-- ColumnDefinition未指定Width时,默认值为"*"(比例分配) -->
<ColumnDefinition />
<!-- 第0列:宽度占比1* -->
<ColumnDefinition/>
<!-- 第1列:宽度占比1*,两列比例1:1,各占Grid宽度的50% -->
</Grid.ColumnDefinitions>
<!-- Border控件布局说明:
1. 未指定Grid.Row,默认放置在第0行;
2. Grid.ColumnSpan="2":表示该控件跨2列显示(同时占据第0列和第1列);
3. Background="Red":设置控件背景色为红色
-->
<Border Grid.RowSpan="2" Background="Red" />
</Grid>

3. Grid 注意事项
- 行 / 列索引从 0 开始,子元素未指定
Grid.Row/Grid.Column时,默认放在第 0 行第 0 列; auto行 / 列会优先占用空间,剩余空间才会分配给*行 / 列;- 跨行列元素会覆盖对应网格区域,需注意布局层级与重叠问题。
二、StackPanel:线性堆栈布局(简单高效的单行 / 列排列)
StackPanel 是 WPF 中最简洁的线性布局控件,子元素沿Orientation指定的方向(垂直 / 水平)依次堆叠,适合固定数量的单行 / 列元素排列。
1. StackPanel 核心特性
- 排列方向:
Orientation="Vertical"(默认,垂直堆叠)/Orientation="Horizontal"(水平堆叠); - 超出处理:子元素总尺寸超出容器时,无滚动条,超出部分直接隐藏;
- 尺寸适配:若父容器行高为
*(非 auto),StackPanel 会在容器中居中显示。
2. StackPanel 实战示例
(1)垂直堆叠:7 个固定尺寸按钮
<!-- ===================== Grid网格布局核心说明 ===================== -->
<!-- Grid是WPF最灵活的布局控件,通过「行(Row)」和「列(Column)」将空间划分为网格 -->
<!-- 所有直接子元素可通过Grid.Row/Grid.Column指定所在行列(默认都在第0行第0列) -->
<Grid>
<!-- ===================== 定义Grid的行集合 ===================== -->
<Grid.RowDefinitions>
<!-- 第0行:Height="auto" 表示行高「自适应内容高度」,内容多高行就多高 -->
<RowDefinition Height="auto"/>
<!-- 第1行:未指定Height,默认值为"*"(星号),表示「占满剩余所有空间」 -->
<!-- 因为第0行是auto,所以第1行高度 = 窗口总高度 - 第0行内容高度 -->
<RowDefinition/>
</Grid.RowDefinitions>
<!-- ===================== 定义Grid的列集合 ===================== -->
<Grid.ColumnDefinitions>
<!-- 第0列:未指定Width,默认值为"*",表示「均分可用宽度」 -->
<ColumnDefinition />
<!-- 第1列:同理第0列,两列无特殊指定时,各占Grid总宽度的50% -->
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<!-- ===================== StackPanel堆栈布局 ===================== -->
<!-- StackPanel是「线性布局控件」,默认垂直(Vertical)堆叠所有子元素 -->
<!-- 该StackPanel未指定Grid.Row/Grid.Column,默认放在Grid的第0行第0列 -->
<StackPanel>
<!-- 多个固定宽高的按钮,StackPanel会垂直依次排列 -->
<!-- 按钮超出StackPanel可视区域时,默认无滚动条,超出部分会被隐藏 -->
<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 个固定尺寸按钮
<Window
x:Class="_01.WPF布局基础.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:_01.WPF布局基础"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<!-- 核心布局容器:Grid(网格布局) -->
<!-- 作用:将容器空间按「行+列」划分为二维网格,是WPF最常用、最灵活的布局控件 -->
<!-- 子元素可通过Grid.Row/Grid.Column附加属性指定所在行列(默认都在第0行第0列) -->
<Grid>
<!-- 定义Grid的行集合(RowDefinitions) -->
<!-- 每行通过RowDefinition定义,Height属性控制行高规则 -->
<Grid.RowDefinitions>
<!-- 第0行:Height="auto" -->
<!-- 规则:行高自适应子元素的实际高度,子元素多高,行就多高 -->
<RowDefinition Height="auto"/>
<!-- 第1行:未显式指定Height(默认值为"*") -->
<!-- 规则:"*"表示占满容器剩余的所有空间 -->
<!-- 实际高度 = Grid总高度 - 第0行的实际高度 -->
<RowDefinition/>
</Grid.RowDefinitions>
<!-- 定义Grid的列集合(ColumnDefinitions) -->
<!-- 每列通过ColumnDefinition定义,Width属性控制列宽规则 -->
<Grid.ColumnDefinitions>
<!-- 第0列:未显式指定Width(默认值为"*") -->
<!-- 规则:"*"表示按比例均分可用宽度 -->
<ColumnDefinition />
<!-- 第1列:未显式指定Width(默认值为"*") -->
<!-- 效果:与第0列均分Grid总宽度,各占50% -->
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<!-- 子布局控件:StackPanel(堆栈布局) -->
<!-- 作用:将子元素按线性方向(水平/垂直)依次排列 -->
<!-- 位置:未指定Grid.Row/Grid.Column,默认在Grid第0行第0列 -->
<StackPanel
<!-- Orientation:排列方向,Horizontal=水平排列,Vertical=垂直排列(默认) -->
Orientation="Horizontal">
<!-- StackPanel子元素:多个固定尺寸的按钮 -->
<!-- 布局特点:水平依次排列,超出StackPanel可视区域时,超出部分会被隐藏(无滚动条) -->
<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>
</Window>

3. 关键优化:去掉 auto 行高实现居中
若将 Grid 第 0 行的Height="auto"改为默认*,StackPanel 会在占满行高的 Grid 中水平居中显示:
<Grid>
<Grid.RowDefinitions>
<RowDefinition /> <!-- 去掉auto,默认* -->
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal">
<!-- 按钮列表 -->
</StackPanel>
</Grid>

三、WrapPanel:自动换行布局(StackPanel 增强版)
WrapPanel 继承了 StackPanel 的线性排列逻辑,但解决了 “超出隐藏” 的问题 —— 子元素超出容器宽度(水平)/ 高度(垂直)时,会自动换行 / 换列,适合动态数量的元素布局(如标签云、按钮列表)。
1. StackPanel vs WrapPanel 对比示例
| 特性 | StackPanel | WrapPanel |
|---|---|---|
| 超出处理 | 隐藏超出部分 | 自动换行 / 列 |
| 空间利用率 | 低(仅沿单方向排列) | 高(自动填充多行 / 列) |
| 适用场景 | 固定数量、单行 / 列元素 | 动态数量、需自适应换行元素 |
<!-- ===================== Grid网格布局核心说明 ===================== -->
<!-- Grid是WPF最灵活的布局控件,通过「行(Row)」和「列(Column)」将空间划分为网格 -->
<!-- 所有直接子元素可通过Grid.Row/Grid.Column指定所在行列(默认都在第0行第0列) -->
<Grid>
<!-- ===================== 定义Grid的行集合 ===================== -->
<Grid.RowDefinitions>
<!-- 第0行:Height="auto" 表示行高「自适应内容高度」,内容多高行就多高 -->
<RowDefinition />
<!-- 第1行:未指定Height,默认值为"*"(星号),表示「占满剩余所有空间」 -->
<!-- 因为第0行是auto,所以第1行高度 = 窗口总高度 - 第0行内容高度 -->
<RowDefinition/>
</Grid.RowDefinitions>
<!-- ===================== 定义Grid的列集合 ===================== -->
<Grid.ColumnDefinitions>
<!-- 第0列:未指定Width,默认值为"*",表示「均分可用宽度」 -->
<ColumnDefinition />
<!-- 第1列:同理第0列,两列无特殊指定时,各占Grid总宽度的50% -->
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<!-- ===================== StackPanel堆栈布局 ===================== -->
<!-- StackPanel是「线性布局控件」,默认垂直(Vertical)堆叠所有子元素 -->
<!-- 该StackPanel未指定Grid.Row/Grid.Column,默认放在Grid的第0行第0列 -->
<StackPanel Orientation="Horizontal">
<!-- 多个固定宽高的按钮,StackPanel会垂直依次排列 -->
<!-- 按钮超出StackPanel可视区域时,默认无滚动条,超出部分会被隐藏 -->
<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>
<!-- ===================== 子布局2:WrapPanel(自动换行布局) ===================== -->
<!-- WrapPanel:线性布局的增强版,子元素超出容器宽度/高度时自动换行/换列 -->
<!-- Grid.Row="1":指定该WrapPanel放在Grid的第1行(默认第0列) -->
<!-- 特性:相比StackPanel不会隐藏超出内容,而是自动换行,更适合动态数量的元素布局 -->
<WrapPanel Grid.Row="1">
<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>
</WrapPanel>
</Grid>

效果:StackPanel 的按钮超出容器宽度后隐藏,而 WrapPanel 会自动换行,所有按钮都能显示。
四、DockPanel:停靠布局(窗体框架首选)
DockPanel 让子元素沿Top/Bottom/Left/Right方向停靠,剩余空间由最后一个子元素填充(可通过LastChildFill关闭),是搭建窗体框架(顶部导航、底部状态栏、侧边栏)的首选。
1. DockPanel 核心规则
- 停靠顺序决定布局:先停靠的元素优先占用空间,后停靠的元素在剩余空间内停靠;
LastChildFill:默认True,最后一个子元素填充剩余空间;设为False则仅显示手动停靠的元素;- 正确停靠逻辑:先停靠
Top/Bottom(纵向),再停靠Left/Right(横向),避免空间挤压。
2. DockPanel 实战示例
<Grid>
<!-- ===================== 定义Grid的行集合(RowDefinitions) ===================== -->
<!-- Grid的行通过RowDefinitions集合定义,每行对应一个RowDefinition对象 -->
<Grid.RowDefinitions>
<!-- 第0行:未显式指定Height,默认值为Auto(自适应内容高度) -->
<!-- Auto特性:行高由该行内子元素的实际高度决定(内容多高,行就多高) -->
<RowDefinition />
<!-- 第1行:未显式指定Height,默认值为"*"(星号,比例分配) -->
<!-- "*"特性:占据Grid剩余的所有空间(此处 = 窗口总高度 - 第0行高度 - 第2行高度 - 第3行高度) -->
<!-- 若多个行都设为"*",则按1:1:1比例分配剩余空间 -->
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<!-- ===================== 第一个DockPanel(默认配置) ===================== -->
<!-- DockPanel:停靠布局控件,核心逻辑是「子元素沿指定方向停靠,剩余空间由最后一个子元素填充」 -->
<!-- 未指定Grid.Row/Grid.Column,默认放在Grid的第0行第0列(Grid默认只有1列) -->
<DockPanel >
<!-- DockPanel核心默认属性:LastChildFill="True"(最后一个子元素自动填充剩余空间) -->
<!-- 子元素未指定DockPanel.Dock时,默认Dock="Left"(向左停靠) -->
<!-- 效果:4个按钮依次向左水平排列,最后一个按钮(按钮4)会填充剩余宽度(因LastChildFill=True) -->
<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>
<!-- ===================== 第二个DockPanel(关闭LastChildFill) ===================== -->
<!-- Grid.Row="1":指定该DockPanel放在Grid的第1行(列默认第0列) -->
<!-- LastChildFill="False":关闭「最后一个子元素填充剩余空间」特性 -->
<DockPanel Grid.Row="1" LastChildFill="False">
<!-- 所有按钮未指定Dock属性,默认Dock="Left"(向左停靠),宽度固定100 -->
<!-- 关键逻辑:LastChildFill="False"时,所有子元素都保持自身尺寸,不会填充剩余空间 -->
<!-- 边界情况:若子元素总宽度(4*100=400)≤DockPanel宽度(窗口宽度800),则全部显示;若超出则超出部分隐藏 -->
<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>
<!-- ===================== 第三个DockPanel(混合停靠方向:布局反例) ===================== -->
<!-- Grid.Row="2":放在Grid第2行 -->
<!-- 核心问题:停靠顺序错误(先横向Left/Right,再纵向Top/Bottom),导致布局挤压 -->
<!-- 逻辑缺陷:
1. 先停靠Left(按钮1)→ 占据左侧100宽度
2. 再停靠Top(按钮2)→ 只能在按钮1右侧的剩余空间里“顶部停靠”,宽度被挤压
3. 再停靠Right(按钮3)→ 在按钮2下方的剩余空间里“右侧停靠”,高度被挤压
4. 最后停靠Bottom(按钮4)→ 空间被严重压缩,显示异常
-->
<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>
<!-- ===================== 第四个DockPanel(修正版:正确的停靠逻辑) ===================== -->
<!-- Grid.Row="3":放在Grid第3行 -->
<!-- LastChildFill="False":关闭自动填充(仅保留手动停靠的元素) -->
<!-- Background="#F0F0F0":浅灰色背景,便于观察DockPanel的边界 -->
<!-- 核心原则:DockPanel停靠顺序决定布局 → 先停靠「纵向(Top/Bottom)」,再停靠「横向(Left/Right)」 -->
<!-- 正确逻辑:
1. 先停靠Top/Bottom:占据完整的上下边缘(无横向挤压,因为纵向停靠优先占满整行宽度)
2. 再停靠Left/Right:在上下按钮之间的剩余空间里,占据左右边缘(无纵向挤压)
-->
<DockPanel Grid.Row="3" LastChildFill="False" Background="#F0F0F0">
<!-- 第一步:先停靠纵向(Top/Bottom)→ 占满整行宽度,无横向挤压 -->
<!-- HorizontalAlignment="Center":按钮水平居中(默认是Stretch,此处手动居中更美观) -->
<Button Width="100" Height="40" DockPanel.Dock="Top" Content="按钮2(上)"
HorizontalAlignment="Center"/>
<!-- 顶部停靠 + 水平居中 -->
<Button Width="100" Height="40" DockPanel.Dock="Bottom" Content="按钮4(下)"
HorizontalAlignment="Center"/>
<!-- 底部停靠 + 水平居中 -->
<!-- 第二步:再停靠横向(Left/Right)→ 在上下按钮之间的剩余空间里占左右边缘 -->
<!-- VerticalAlignment="Center":按钮垂直居中(默认是Stretch,此处手动居中更美观) -->
<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 实战示例
<!--
布局说明:
1. Grid是WPF最基础的布局控件(网格布局),支持自定义行/列划分
2. UniformGrid是Grid的简化版(均匀网格),自动将空间平均分配给子元素,
无需手动定义行/列尺寸,适合需要"等分空间"的场景(如计算器按钮、九宫格等)
-->
<Grid>
<!--
UniformGrid属性说明:
- Columns:设置列数(此处为4列)
- Rows:设置行数(此处为3行)
- 特性:所有单元格尺寸完全相同,子元素会自动填充到单元格中,
即使子元素数量少于单元格总数,剩余单元格为空;若多于则自动换行/列
-->
<UniformGrid Columns="4" Rows="3">
<!-- 子元素:Button按钮(共9个,填充4列3行的12个单元格中的前9个) -->
<Button Content="按钮1"/> <!-- 补充Content属性,便于可视化 -->
<Button Content="按钮2"/>
<Button Content="按钮3"/>
<Button Content="按钮4"/>
<Button Content="按钮5"/>
<Button Content="按钮6"/>
<Button Content="按钮7"/>
<Button Content="按钮8"/>
<Button Content="按钮9"/>
</UniformGrid>
</Grid>

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

1090

被折叠的 条评论
为什么被折叠?



