# Form 表单 ## 概述 表单(Form)是数据录入场景中最核心的复合控件,用于收集、校验和提交用户输入。表单将多个数据录入控件(输入框、选择器、日期选择器等)组织在统一的布局中,提供字段级和表单级的验证能力,以及提交/重置等操作流程。 AtomUI 的 `Form` 控件完整复刻了 [Ant Design 5.0 Form](https://ant.design/components/form-cn) 的设计规范,在 .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` 控制,支持响应式断点: ```xml ``` ### 验证生命周期 1. **触发**:用户操作(值变化 / 失焦 / 提交)触发验证 2. **防抖**:如果设置了 `ValidateDebounce`,延迟指定时间后执行 3. **执行**:按 `ValidateStrategy` 执行 `Validators` 列表中的验证器 4. **结果**:每个验证器返回 `FormValidateResult`(Success / Error / Warning) 5. **通知**:更新 `ValidateStatus`、错误/警告消息、通知子控件更新状态图标 6. **汇总**:Form 级别汇总所有 FormItem 的验证结果,更新 `IsFormValid` ### IFormItemAware 集成 所有可参与表单验证的控件必须实现 `IFormItemAware` 接口: ```csharp 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` 包装: ```xml machines ``` ### 提交/重置按钮路由 `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` | 使用范例 |