jk's notes
  • CH06 布局控件

CH06 布局控件

布局控件用于包含, 排版其他控件.

概览

下面是需要了解的布局控件

控件作用
Canvas在 Canvas 使用 Left, Top, Right, Bottom 进行布局.
DockPanel在边缘停靠.
Expander显示一个标题和一个图标, 用户点击后可以显示/隐藏一个子控件.
Grid采用行列的方式进行布局. 如果需要可忽略行列, 像 Canvas 一样布局.
ScrollViewer在一个滚动区域内显示单个子控件.
StackPanel以单行/列的形式进行布局.
StatusBar在窗体底部创建一个区域, 来显示一些状态信息.
TabControl展示一组 Tab, 并允许用户选择显示.
ToolBar一组横向或纵向的工具栏.
ToolBarTray处理工具栏的尺寸调整, 拖拽等安排.
UniformGrid以同样尺寸的行或列编排内容.
Viewbox以各种方式拉伸其内容.
WindowsFormsHost用于容纳 Windows Forms 的控件.
WrapPanel展示行/列中的子元素.

CANVAS

Canvas 中的元素使用距离 Canvas 的上下左右边距进行定位, Canvas 会提供附加属性到其子元素中.

如果同时使用 Top, Left, Right, Bottom, 那么默认 Top 和 Left 生效.

Canvas 如果尺寸会变化, 那么其内部元素会保留其设置的距离, 如果要实现自适应, 建议使用其他布局方式.

jk: 基本可以理解为 HTML 中的 绝对定位的布局模式.

DOCKPANEL

DockPanel 子元素会在其上下左右进行停靠. 只需要设置其子元素的附加属性 Dock 为 Top, Right, Bottom, 或 Left.

DockPanel 的 LastCHildFill 设置为 true (默认), 那么最后一个元素会填充所有剩下的空间.

<DockPanel LastChildFill="False">
    <Border DockPanel.Dock="Top" BorderBrush="Black" BorderThickness="1">
        <Label Content="Label Content" />
    </Border>
    <Border DockPanel.Dock="Top" BorderBrush="Black" BorderThickness="1">
        <Label Content="Label Content" />
    </Border>
</DockPanel>

image-20250620174735128

DockPanel 中的元素布局与 HTML 中的 DIV 类似, 它会默认占据一整个区域, 即使可以设置宽和高, 但是区域是被占据的. 后续的元素是在剩下的空间中进行停靠与对齐.

<DockPanel LastChildFill="False">
    <Border DockPanel.Dock="Top" Width="100" Height="100" BorderBrush="Black" BorderThickness="1">
        <Label Content="Label Content" />
    </Border>
    <Border DockPanel.Dock="Left" Width="100" Height="200" BorderBrush="Black" BorderThickness="1">
        <Label Content="Label Content" />
    </Border>
    <Border DockPanel.Dock="Right" BorderBrush="Black" BorderThickness="1">
        <Label Content="Label Content" />
    </Border>
</DockPanel>

image-20250620175451070

EXPANDER

逻辑上是折叠面板, 显示一个标题与一个箭头图标, 单击后会展开与折叠其子元素. 结合 StackPanel 可以实现手风琴布局.

常用属性:

属性含义
Background背景色, 包括标题与内容, 整个部分的背景色.
BorderBrush整个控件的边框颜色. BorderThickness 可设置宽度.
BorderThickness边框宽度.
ExpandDirection展开方向. 可取值为 Down (默认), Left, Bottom, 和 Right.
Foreground标题的文本颜色.
Header标题内容.
IsExpanded是否展开.

GRID

jk: 很重要的布局容器.

Grid 适用行列的形式来定义表格布局. 定义的语法:

<Grid>
	<Grid.ColumnDefinitions>
  	<ColumnDefinition Width="*" />
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
  	<RowDefinishtion Height="*" />
  </Grid.RowDefinitions>
</Grid>

定义了行与列后, 需要说明的是单位. 默认为像素, 还可以是 cm, in, px, 以及 pt.

还可以是相对尺寸, 使用 * 表示, 然后使用数字表示一定的倍数.

Grid 中的内容使用附加属性 Grid.Row 和 Grid.Column 来指定控件放在那个位置. 索引采用 0-base.

使用附加属性 Grid.RowSpan 和 Grid.ColumnSpan 来设置元素跨行与跨列.

布局时, 可以使用属性 ShowGridLines="True" 来显示表格线.

SCROLLVIEWER

ScrollViewer 可以容纳单个子节点, 采用一个滚动区域来展示.

比较重要的属性是: HorizontalScrollBarVisibility 和 VerticalScrollBarVisibility. 其可取值有:

  • Auto 根据内容显示与隐藏滚动条.
  • Visible 无论如何都会显示滚动条.
  • Disabled 无论如何都不显示滚动条. 子元素的大小会被设置为容器大小.
  • Hidden 无论如何都不会显示滚动条, 但子元素也不会调整尺寸.

jk: 作者给出的案例, 然后一一解释, 挺详细的.

STACKPANEL

以横向或纵向的方式排列内容. 逻辑上有点像单向的 DockPanel.

使用属性: Orientation 来控制方向, 取值为: Horizontal 和 Vertical (默认).

STATUSBAR

在窗体底部开辟一块区域用于显示状态信息. 理论上应包含只读的控件, 包括 图标, Label, 以及 ProgressBar 等.

StatusBar 需要包含 StatusBarItem, 该控件是单子元素控件.

感觉很多 WPF 控件都是语义化的控件, 比如这个 StatusBar 和 StatusBarItem, 没指定宽高的时候也是在 Grid 中被填充, 然后内容被设置为有一定间距的一一排开. 具体布局还是需要设置宽高, 和 Grid 等组件联合实现布局.

TABCONTROL

基本语法:

<TabControl>
    <TabItem Header="标题">
        内容1
    </TabItem>
    <TabItem Header="标题2">
        内容2
    </TabItem>
    <TabItem Header="标题3">
        内容3
    </TabItem>
</TabControl>

TabItem 是单子元素控件. 如果要自定义 Header 可以使用标签语法.

用法越来越像 HTML

TOOLBAR 与 TOOLBARTRAY

ToolBar 在一个区域中放置用户需要的工具控件. 例如按钮, 下拉框等.

多个 ToolBar 可以放在一个 ToolBarTray 中. 然后在 ToolBar 中可以放置按钮, 下拉框, 文本框等其他控件.

ToolBarTray 提供了两个附加属性, 来控制内部的 ToolBar 的位置, 一个是 Band, 另一个是 BandIndex.

这两个属性用在 ToolBar 上, Band 可以理解为行, BandIndex 可以理解为列, 按照行列进行排序. 其取值都是数字, 没有固定的大小与要求, 只是会使用它排序, 来排列控件. 逻辑上与 CSS 中的 z-index 一样.

当 ToolBar 内容过多时, 会在溢出区显示控件. 使用附加属性 ToolBar.OverflowMode 来控制溢出区的显示. 可取值有: Never, Always, 以及 AsNeeded.

ToolBarTray 默认是横向摆放的, 还有一个属性 Orientation, 取值为 Horizontal 和 Vertical, 可以控制其竖向摆放. 但是需要使用 LayoutTransform 来旋转其中的控件来处理显示的错误.

置于这个怎么旋转, 还是需要例子来看看.

UNIFORMGRID

可以理解为矩阵式布局, 所有的行列均一样. 并采用先行后列的顺序依次排列. 使用属性 Rows 和 Columns 来定义其行数与列数.

<Window x:Class="_05_内容控件.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:_05_内容控件"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800" FontSize="30">
    <UniformGrid Rows="4" Columns="3">
        <Button>1</Button>
        <Button>2</Button>
        <Button>3</Button>
        <Button>4</Button>
        <Button>5</Button>
        <Button>6</Button>
        <Button>7</Button>
        <Button>8</Button>
        <Button>9</Button>
        <Label/>
        <Button>0</Button>
        <Label/>
    </UniformGrid>
</Window>

image-20250620213153925

VIEWBOX

单个子元素的容器, 内容会被拉伸填充整个容器. 其拉伸方式由属性 Stretch 指定, 可取值有:

  • None 不会被拉伸.
  • Fill 按照容器尺寸拉伸, 但可能会使得失真.
  • Uniform 按比例拉伸, 会显示完整的内容.
  • UniformToFill 按比例拉伸, 尽可能的大, 但是会切除部分内容.

image-20250620214349366

WINDOWSFORMSHOST

略, 可以认为是组件不足的时候的临时方案.

WRAPPANEL

逻辑上就是流式布局, 按照行或列的方式堆砌子控件. 当行或列不足以放下内容的时候会开启新行/列来继续堆砌.

可以使用 Orientation 来设置按照行, 还是列来进行堆砌.

小结

略

Last Updated:
Contributors: jk