8.7 KiB
GroupBox 分组框
概述
分组框(GroupBox)用于将一组相关的控件组织在一起,并通过标题为其提供视觉上的分组标识。它在概念上类似于 HTML 的 <fieldset> 元素——一个带标题的围栏,将逻辑上相关的表单字段或内容归拢到一起。
这是 AtomUI 的扩展控件,在 Ant Design 5.0 中没有直接对应的组件。在设计语言上,它最接近 Ant Design 的 Card 组件(带标题的内容容器),但 GroupBox 采用了经典的「边框从标题中间穿过、标题区域遮挡边框」的 fieldset 式视觉效果,更适合表单分组和配置面板等场景。
设计原理
传统 GroupBox 的设计哲学
GroupBox 是桌面 GUI 的经典控件(WinForms、WPF、Qt 等均有内置),其核心设计意图是:
- 视觉分组:通过边框围栏将相关控件聚合在一起,帮助用户快速识别功能区域
- 标题标注:在边框顶部放置标题文本,为分组提供语义说明
- 内容容纳:作为容器承载任意子控件
Avalonia 基础能力
Avalonia 框架本身没有内置 GroupBox 控件。AtomUI 的 GroupBox 直接继承自 Avalonia 的 ContentControl,利用其内容容纳和模板化能力,在此基础上实现了 fieldset 式的分组视觉效果。
Avalonia ContentControl 提供的基础能力:
| 属性 | 说明 |
|---|---|
Content |
容器内容,可以是任意控件或布局面板 |
ContentTemplate |
内容数据模板 |
Background |
背景画刷 |
BorderBrush |
边框画刷 |
BorderThickness |
边框厚度 |
CornerRadius |
圆角半径 |
Padding |
内容区域内间距 |
IsEnabled |
是否启用 |
AtomUI GroupBox 的扩展设计
AtomUI GroupBox 在 ContentControl 的基础上做了以下扩展:
| 扩展能力 | 实现方式 | 设计动机 |
|---|---|---|
| 标题文本 | HeaderTitle 属性 |
为分组提供文字标注 |
| 标题位置 | HeaderTitlePosition 枚举(Left / Center / Right) |
支持三种标题对齐方式,适应不同布局风格 |
| 标题图标 | HeaderIcon 属性(PathIcon 类型) |
在标题文本前显示图标,增强语义辨识 |
| 标题字体定制 | HeaderFontSize / HeaderFontStyle / HeaderFontWeight |
精细控制标题的字体外观 |
| 标题颜色 | HeaderTitleColor 属性 |
自定义标题文本颜色 |
| Fieldset 式边框 | 自定义 Render 方法 + BorderRenderHelper |
复刻经典 fieldset 效果:边框从标题垂直中心开始绘制,标题区域用背景色遮挡边框 |
| Design Token | GroupBoxToken + RegisterTokenResourceScope |
所有视觉值从全局/组件级 Token 派生,支持主题切换 |
功能详解
标题位置(HeaderTitlePosition)
标题位置通过 HeaderTitlePosition 属性设置,支持三种对齐方式:
| 位置 | 视觉效果 | 典型用途 |
|---|---|---|
Left(默认) |
标题左对齐 | 最常见的分组标题位置 |
Center |
标题居中 | 对称布局、居中型面板 |
Right |
标题右对齐 | 特殊布局需求 |
标题图标(HeaderIcon)
通过 HeaderIcon 属性在标题文本左侧添加图标。图标使用 Ant Design 图标集提供,显示在标题文本之前,图标与文本之间通过 HeaderIconMargin Token 控制间距。
标题字体定制
GroupBox 提供三个属性精细控制标题的字体外观:
HeaderFontSize:标题字号(默认由SharedToken.FontSize控制)HeaderFontStyle:字体风格(Normal / Italic / Oblique)HeaderFontWeight:字重(Normal / Bold / Medium 等)HeaderTitleColor:标题颜色(默认由SharedToken.ColorText控制)
Fieldset 式边框渲染
GroupBox 最核心的视觉特征是「边框从标题中间穿过」的效果。实现原理如下:
- 布局阶段(
ArrangeOverride):计算标题容器的垂直中心位置,以此作为边框的起始 Y 坐标 - 渲染阶段(
Render):- 首先通过
BorderRenderHelper在偏移后的位置绘制边框和背景(边框区域从标题垂直中心开始到控件底部) - 然后在标题容器的精确位置绘制一个矩形遮挡区域,用背景色填充以「擦除」标题下方的边框线段
- 首先通过
这种两阶段渲染创造了标题「嵌入」边框的经典 fieldset 视觉效果。
┌── Title Info ──────────────────────┐
│ │ ← 边框从标题垂直中心开始
│ Content of group box │
│ │
└────────────────────────────────────┘
↑ 标题区域的边框被背景色遮挡
与 Ant Design 规范的对齐程度
GroupBox 是 AtomUI 的扩展控件,在 Ant Design 5.0 中没有直接对应的组件。
| 特性 | Ant Design (React) | AtomUI (Avalonia) | 说明 |
|---|---|---|---|
| 分组容器 | Card 组件(最接近) |
GroupBox |
设计理念类似,但 GroupBox 采用 fieldset 式边框 |
| Divider(带标题分割线) | Divider 组件 |
— | GroupBox 的标题位置效果与 Divider 有些类似 |
| 标题位置 | Card 不支持标题对齐 |
✅ Left / Center / Right | AtomUI 扩展功能 |
| 标题图标 | Card 不内置图标栏位 |
✅ HeaderIcon 属性 |
AtomUI 扩展功能 |
| 标题字体定制 | 通过 CSS 自定义 | ✅ 内置属性 | AtomUI 提供开箱即用的字体控制 |
继承关系
Avalonia.Controls.Primitives.TemplatedControl
└── Avalonia.Controls.ContentControl
└── AtomUI.Desktop.Controls.GroupBox
GroupBox 没有在 AtomUI.Controls 中定义抽象基类,因为它是桌面端特有的扩展控件。如果未来需要移动端对应实现,可以抽取公共逻辑到 AtomUI.Controls 层。
各层级职责划分:
| 层级 | 提供的能力 |
|---|---|
ContentControl |
任意内容容纳、Content / ContentTemplate、ContentPresenter 模板化呈现、Background / BorderBrush / BorderThickness / CornerRadius / Padding 等视觉属性 |
AtomUI.Desktop.Controls.GroupBox |
标题文本/位置/图标/字体定制、Fieldset 式边框渲染(自定义 Render)、Design Token 集成 |
源码位置
| 层级 | 文件路径 | 说明 |
|---|---|---|
| 控件类 | src/AtomUI.Desktop.Controls/GroupBox/GroupBox.cs |
GroupBox 桌面端实现 |
| Token 定义 | src/AtomUI.Desktop.Controls/GroupBox/GroupBoxToken.cs |
组件级 Design Token |
| 主题模板 | src/AtomUI.Desktop.Controls/GroupBox/Themes/GroupBoxTheme.axaml |
ControlTheme AXAML |
| 模板常量 | src/AtomUI.Desktop.Controls/GroupBox/Themes/GroupBoxThemeConstants.cs |
模板部件名称常量 |
| Gallery 示例 | controlgallery/AtomUIGallery/ShowCases/Views/DataDisplay/GroupBoxShowCase.axaml |
使用范例 |
模板结构
GroupBox 的 ControlTemplate 结构如下:
Border#PART_Frame ← 主框架(承载布局,但实际边框由 Render 绘制)
└── DockPanel (LastChildFill=True) ← 内容布局容器
├── Panel#PART_HeaderContainer ← 标题区域容器(DockPanel.Dock="Top")
│ └── Decorator#PART_HeaderContent ← 标题内容定位器(控制 HorizontalAlignment)
│ └── StackPanel (Horizontal) ← 图标 + 文本水平排列
│ ├── IconPresenter#PART_HeaderIconPresenter ← 标题图标
│ └── TextBlock#PART_HeaderPresenter ← 标题文本
└── ContentPresenter#PART_ContentPresenter ← 用户内容区域(填充剩余空间)
设计要点:
- 边框和背景不通过
Border#PART_Frame的属性绘制,而是通过GroupBox.Render()自定义绘制,以实现标题遮挡边框的 fieldset 效果 - 标题位置通过
Decorator#PART_HeaderContent的HorizontalAlignment控制(Left / Center / Right) - 标题图标通过
IsVisible绑定HeaderIcon属性是否为 null 来控制显隐
模板部件常量
| 常量名 | 值 | 说明 |
|---|---|---|
GroupBoxThemeConstants.FramePart |
"PART_Frame" |
主框架 Border |
GroupBoxThemeConstants.HeaderContainerPart |
"PART_HeaderContainer" |
标题区域容器 Panel |
GroupBoxThemeConstants.HeaderContentPart |
"PART_HeaderContent" |
标题内容定位器 Decorator |
GroupBoxThemeConstants.HeaderIconPresenterPart |
"PART_HeaderIconPresenter" |
标题图标展示器 |
GroupBoxThemeConstants.HeaderPresenterPart |
"PART_HeaderPresenter" |
标题文本 TextBlock |
GroupBoxThemeConstants.ContentPresenterPart |
"PART_ContentPresenter" |
内容展示器 |