15 KiB
Form 表单
概述
表单(Form)是数据录入场景中最核心的复合控件,用于收集、校验和提交用户输入。表单将多个数据录入控件(输入框、选择器、日期选择器等)组织在统一的布局中,提供字段级和表单级的验证能力,以及提交/重置等操作流程。
AtomUI 的 Form 控件完整复刻了 Ant Design 5.0 Form 的设计规范,在 .NET / Avalonia 平台上提供与 Ant Design React 版一致的表单体验。表单系统由多个协作控件组成:Form(容器)、FormItem(字段项)、FormActionsItem(操作区)、SubmitButton(提交按钮)、ResetButton(重置按钮)和 FormItemDecorator(装饰器)。
设计原理
Ant Design 的表单设计哲学
Ant Design 对表单的定位是:「高性能表单控件,自带数据域管理。包含数据录入、校验以及对应样式」。其核心设计理念包括:
三种表单布局:
| 布局 | 设计意图 | 典型用途 |
|---|---|---|
| 📐 水平布局(Horizontal) | 标签在左、控件在右,一行一个字段。适合字段数量适中、标签宽度统一的场景 | 注册表单、设置页面、数据编辑 |
| 📏 垂直布局(Vertical) | 标签在上、控件在下,每个字段独占一行。标签不受宽度限制 | 移动端表单、标签文本较长的场景 |
| ➡️ 内联布局(Inline) | 所有字段水平排列在同一行,紧凑布局 | 搜索栏、筛选条件、导航栏登录 |
验证体系:
| 特性 | 说明 |
|---|---|
| 🔴 必填标记 | 视觉提示用户该字段必填,支持 Default / Optional / Hidden / Customize 四种标记模式 |
| ⚡ 验证触发 | 支持值变化时(OnChanged)、失焦时(OnBlur)、提交时(OnSubmit)三种触发方式 |
| 🕐 防抖验证 | 通过 ValidateDebounce 降低高频验证对后端的压力 |
| 🔗 验证策略 | 遇到第一个错误即停(StopWhenFirstFailed)、顺序执行(Sequential)、并行执行(Parallel) |
| ⚠️ 仅警告规则 | WarningOnly 标记的验证器不阻止表单提交,仅显示警告信息 |
| 🔄 验证反馈 | 在输入控件内显示验证状态图标(成功✓ / 警告⚠ / 错误✗ / 验证中⏳) |
Avalonia 基础能力
AtomUI 的 Form 继承自 Avalonia 的 ItemsControl,而 FormItem 继承自 TemplatedControl。
Avalonia ItemsControl 的核心职责:
ItemsControl 是 Avalonia 中用于展示集合数据的基础控件,它管理一组子项(Items),支持容器化(ContainerForItemOverride)和数据模板化。Form 利用这一机制将每个 FormItem 作为子项进行管理。
Control → TemplatedControl → ItemsControl → Form
Control → TemplatedControl → FormItem
AtomUI 的扩展设计
AtomUI Form 在 Avalonia ItemsControl 的基础上,遵循 Ant Design 5.0 规范做了以下扩展:
| 扩展能力 | 实现方式 | 设计动机 |
|---|---|---|
| 三种表单布局 | FormLayout 枚举(Horizontal / Vertical / Inline) |
对齐 Ant Design 的 layout 属性 |
| 字段验证系统 | IFormValidator 接口 + FormValidatorProvider + 内置验证器 |
声明式验证配置,支持异步验证 |
| 三种验证触发 | FormValidateTrigger 枚举 |
对齐 Ant Design 的 validateTrigger |
| 三种验证策略 | FormValidateStrategy 枚举 |
支持短路、顺序、并行三种执行方式 |
| 四种必填标记 | FormRequiredMark 枚举 + 自定义标记模板 |
对齐 Ant Design 的 requiredMark |
| 表单操作路由 | SubmitButton / ResetButton 路由事件冒泡 |
任意位置的提交/重置按钮自动关联到 Form |
| 初始值/重置 | InitialValues + Reset() |
支持表单数据的初始化和重置 |
| 表单值收集 | IFormValues / FormValues |
统一的表单值收集与提交 |
| 动态表单项 | Items.Add() / DeleteFormItem() |
运行时动态增删表单字段 |
| 尺寸统一 | ISizeTypeAware |
全局控制所有子控件尺寸 |
| 样式变体 | IInputControlStyleVariantAware |
Outlined / Filled / Borderless / Underlined |
| 验证反馈图标 | IsValidateFeedbackEnabled + FormValidateFeedback |
输入框内显示验证状态图标 |
| 标签列比例 | LabelColInfo / WrapperColInfo(MediaBreakGridLength) |
响应式标签与内容宽度分配 |
| Design Token | FormToken + RegisterTokenResourceScope |
所有视觉值从全局 Token 派生 |
功能详解
表单布局(FormLayout)
布局通过 FormLayout 属性设置。Form 根据布局模式决定内部排列方向和 FormItem 的标签/内容排布方式。
| 布局 | Form 排列方向 | FormItem 内部布局 | 说明 |
|---|---|---|---|
Horizontal |
垂直(一行一个 FormItem) | 标签在左、内容在右(FormItemLayout.Horizontal) |
默认布局,最常用 |
Vertical |
垂直(一行一个 FormItem) | 标签在上、内容在下(FormItemLayout.Vertical) |
标签独占一行 |
Inline |
水平(多个 FormItem 同一行) | 标签在左、内容在右(FormItemLayout.Horizontal) |
紧凑搜索栏 |
FormItem 的 Layout 属性可以独立覆盖:在 Horizontal 或 Vertical 的表单中,个别 FormItem 可以通过设置自身的 Layout 属性来使用不同的排布方式。
标签与内容宽度(LabelColInfo / WrapperColInfo)
在水平布局中,标签和内容区域的宽度通过 MediaBreakGridLength 控制,支持响应式断点:
<!-- 固定比例 -->
<atom:Form LabelColInfo="8*" WrapperColInfo="16*" />
<!-- 固定像素宽度 -->
<atom:Form LabelColInfo="200" WrapperColInfo="*" />
<!-- 单个 FormItem 覆盖 -->
<atom:FormItem LabelColInfo="4*" WrapperColInfo="20*" Layout="Horizontal" />
验证生命周期
- 触发:用户操作(值变化 / 失焦 / 提交)触发验证
- 防抖:如果设置了
ValidateDebounce,延迟指定时间后执行 - 执行:按
ValidateStrategy执行Validators列表中的验证器 - 结果:每个验证器返回
FormValidateResult(Success / Error / Warning) - 通知:更新
ValidateStatus、错误/警告消息、通知子控件更新状态图标 - 汇总:Form 级别汇总所有 FormItem 的验证结果,更新
IsFormValid
IFormItemAware 集成
所有可参与表单验证的控件必须实现 IFormItemAware 接口:
public interface IFormItemAware
{
event EventHandler ValueChanged; // 值变化事件
void SetFormValue(object? value); // 外部设置值
object? GetFormValue(); // 获取当前值
void ClearFormValue(); // 清除值(重置)
void NotifyValidateStatus(FormValidateStatus status); // 通知验证状态
}
AtomUI 内置的数据录入控件(LineEdit、Select、DatePicker、CheckBox 等)均已实现此接口。自定义控件需要实现该接口才能参与表单验证。
FormItemDecorator
当一个 FormItem 内需要在主控件旁边附加额外内容(如单位文本)时,使用 FormItemDecorator 包装:
<atom:FormItem LabelText="InputNumber" FieldName="inputNumber">
<atom:FormItemDecorator>
<atom:NumericUpDown Minimum="1" Maximum="10" Width="120"/>
<atom:FormItemDecorator.Extra>
machines
</atom:FormItemDecorator.Extra>
</atom:FormItemDecorator>
</atom:FormItem>
提交/重置按钮路由
SubmitButton 和 ResetButton 通过路由事件(Bubble)与 Form 通信,无论放在 Form 内部的任何位置,事件都会冒泡到最近的 Form 容器:
SubmitButton.SubmitEvent→Form.HandleSubmitButtonClick→Form.Submit()ResetButton.ResetEvent→Form.HandleResetButtonClick→Form.Reset()
动态表单项
Form 支持在运行时动态添加和删除 FormItem:
- 添加:
form.Items.Add(newFormItem)或form.Items.Insert(index, newFormItem) - 删除:
form.DeleteFormItem(formItem)或设置IsShowItemDeleteButton显示删除按钮 - 最少数量:
MinItemCount控制最少保留的数据项数量,少于此数量时删除按钮自动隐藏
SubmitButton 的 IsWatchValidateResult
当 IsWatchValidateResult="True" 时,SubmitButton 会实时监听 Form 的 IsFormValid 属性变化,自动启用/禁用按钮。只有当所有必填字段验证通过后,提交按钮才变为可用状态。
与 Ant Design 规范的对齐程度
| 特性 | Ant Design (React) | AtomUI (Avalonia) | 对齐情况 |
|---|---|---|---|
三种布局 layout |
✅ horizontal / vertical / inline |
✅ FormLayout 枚举 |
✅ 完全对齐 |
字段校验 rules |
✅ 声明式规则数组 | ✅ Validators 属性 + FormValidatorProvider |
✅ 对齐(语法不同,能力一致) |
验证触发 validateTrigger |
✅ onChange / onBlur / onSubmit |
✅ FormValidateTrigger 枚举 |
✅ 完全对齐 |
必填标记 requiredMark |
✅ boolean / 'optional' |
✅ FormRequiredMark 枚举(Default / Hidden / Optional / Customize) |
✅ 扩展对齐(增加 Customize) |
表单方法 submit / reset |
✅ 实例方法 | ✅ Submit() / Reset() 方法 |
✅ 完全对齐 |
初始值 initialValues |
✅ 对象属性 | ✅ InitialValues 属性 |
✅ 完全对齐 |
动态增删字段 Form.List |
✅ 专用组件 | ✅ Items.Add/Remove + DeleteFormItem |
⚠️ 方式不同,能力覆盖 |
仅警告规则 warningOnly |
✅ 规则属性 | ✅ IFormValidator.WarningOnly |
✅ 完全对齐 |
验证反馈 hasFeedback |
✅ 属性 | ✅ IsValidateFeedbackEnabled |
✅ 完全对齐 |
标签对齐 labelAlign |
✅ left / right |
✅ FormLabelAlign 枚举 |
✅ 完全对齐 |
标签换行 labelWrap |
✅ 布尔属性 | ✅ LabelWrapping 属性 |
✅ 完全对齐 |
尺寸 size |
✅ small / middle / large |
✅ SizeType 属性 |
✅ 完全对齐 |
变体 variant |
✅ outlined / filled / borderless |
✅ StyleVariant + Underlined |
✅ 扩展对齐 |
显示冒号 colon |
✅ 布尔属性 | ✅ IsShowColon 属性 |
✅ 完全对齐 |
字段联动 dependencies |
✅ 声明式 | ✅ NotifyFormItemChanged |
⚠️ 基础支持 |
Form.Provider |
✅ 多表单联动 | ❌ 暂未实现 | ⚠️ 待支持 |
useWatch |
✅ Hook | ❌ 不适用(非 React) | — 平台差异 |
scrollToFirstError |
✅ 布尔/对象 | ✅ ScrollToFirstError 属性(预留) |
⚠️ 属性已定义 |
继承关系
Form(表单容器):
Avalonia.Controls.Primitives.TemplatedControl
└── Avalonia.Controls.ItemsControl
└── AtomUI.Desktop.Controls.Form
├── implements ISizeTypeAware
├── implements IMotionAwareControl
├── implements IForm
└── implements IInputControlStyleVariantAware
FormItem(表单字段项):
Avalonia.Controls.Primitives.TemplatedControl
└── AtomUI.Desktop.Controls.FormItem
└── implements IFormItem
FormActionsItem(操作区):
AtomUI.Desktop.Controls.FormItem
└── AtomUI.Desktop.Controls.FormActionsItem
SubmitButton / ResetButton:
AtomUI.Desktop.Controls.Button
├── AtomUI.Desktop.Controls.SubmitButton
└── AtomUI.Desktop.Controls.ResetButton
FormItemDecorator(字段装饰器):
Avalonia.Controls.Primitives.TemplatedControl
└── AtomUI.Desktop.Controls.FormItemDecorator
├── implements IFormItemAware
├── implements IFormItemFeedbackAware
├── implements ISizeTypeAware
├── implements IMotionAwareControl
└── implements IInputControlStyleVariantAware
各层级职责划分:
| 层级 | 提供的能力 |
|---|---|
ItemsControl |
子项集合管理(Items)、容器创建(CreateContainerForItemOverride)、数据模板化 |
Form |
表单布局(三种)、全局验证配置、提交/重置流程、值收集、动态增删、Design Token 集成 |
FormItem |
字段标签、验证器绑定、验证状态管理、错误消息展示、标签/内容响应式布局 |
FormActionsItem |
非数据项容器(用于放置按钮等操作控件),跳过验证 |
SubmitButton / ResetButton |
路由事件触发提交/重置,IsWatchValidateResult 自动禁用 |
FormItemDecorator |
包装子控件并附加额外内容,代理 IFormItemAware 接口 |
源码位置
| 层级 | 文件路径 | 说明 |
|---|---|---|
| 表单容器 | src/AtomUI.Desktop.Controls/Form/Form.cs |
Form 桌面端实现 |
| 表单字段项 | src/AtomUI.Desktop.Controls/Form/FormItem.cs |
FormItem / FormActionsItem |
| 字段装饰器 | src/AtomUI.Desktop.Controls/Form/FormItemDecorator.cs |
FormItemDecorator |
| 提交按钮 | src/AtomUI.Desktop.Controls/Form/SubmitButton.cs |
SubmitButton |
| 重置按钮 | src/AtomUI.Desktop.Controls/Form/ResetButton.cs |
ResetButton |
| 删除按钮 | src/AtomUI.Desktop.Controls/Form/ItemDeleteButton.cs |
ItemDeleteButton |
| Token 定义 | src/AtomUI.Desktop.Controls/Form/FormToken.cs |
组件级 Design Token |
| 枚举定义 | src/AtomUI.Controls/Form/FormEnums.cs |
共享枚举(跨平台) |
| 接口定义 | src/AtomUI.Controls/Form/IForm.cs |
IForm 接口 |
| 接口定义 | src/AtomUI.Controls/Form/IFormItem.cs |
IFormItem 接口 |
| 接口定义 | src/AtomUI.Controls/Form/IFormItemAware.cs |
IFormItemAware / IFormItemFeedbackAware |
| 接口定义 | src/AtomUI.Controls/Form/IFormValidator.cs |
IFormValidator 接口 |
| 验证器基类 | src/AtomUI.Controls/Form/Validators/AbstractFormValidator.cs |
验证器抽象基类 |
| 内置验证器 | src/AtomUI.Controls/Form/Validators/FormStringNotEmptyValidator.cs |
字符串非空验证 |
| 内置验证器 | src/AtomUI.Controls/Form/Validators/FormStringLengthValidator.cs |
字符串长度验证 |
| 内置验证器 | src/AtomUI.Controls/Form/Validators/FormUrlValidator.cs |
URL 格式验证 |
| 内置验证器 | src/AtomUI.Controls/Form/Validators/FormNotNullValidator.cs |
非空验证 |
| 内置验证器 | src/AtomUI.Controls/Form/Validators/FormAssertValidator.cs |
断言验证(用于测试) |
| 主题模板 | src/AtomUI.Desktop.Controls/Form/Themes/FormTheme.axaml |
Form ControlTheme |
| 主题模板 | src/AtomUI.Desktop.Controls/Form/Themes/FormItemTheme.axaml |
FormItem ControlTheme |
| 主题模板 | src/AtomUI.Desktop.Controls/Form/Themes/FormItemDecoratorTheme.axaml |
FormItemDecorator ControlTheme |
| 主题模板 | src/AtomUI.Desktop.Controls/Form/Themes/SubmitButtonTheme.axaml |
SubmitButton ControlTheme |
| 主题模板 | src/AtomUI.Desktop.Controls/Form/Themes/ResetButtonTheme.axaml |
ResetButton ControlTheme |
| 主题注册 | src/AtomUI.Desktop.Controls/Form/Themes/FormThemes.axaml |
主题资源注册 |
| 模板常量 | src/AtomUI.Desktop.Controls/Form/Themes/FormThemeConstants.cs |
模板部件名称常量 |
| Gallery 示例 | controlgallery/AtomUIGallery/ShowCases/Views/DataEntry/FormShowCase.axaml |
使用范例 |