Files

176 lines
8.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 最核心的视觉特征是「边框从标题中间穿过」的效果。实现原理如下:
1. **布局阶段**(`ArrangeOverride`):计算标题容器的垂直中心位置,以此作为边框的起始 Y 坐标
2. **渲染阶段**(`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"` | 内容展示器 |