# Epic 2 Details: PropertyGrid - Auto-Generated Configuration UI ### Epic Goal 实现 PropertyGrid 控件,这是控件库的核心价值所在。该控件能够从数据模型自动生成属性编辑 UI,支持 string, int, double, bool, enum, DateTime 六种基础类型,以及属性分组、只读属性等功能。Epic 完成后,上位机和 AI 应用开发者可以快速构建配置界面,无需手写大量 XAML。该 Epic 在开发过程中会产出必要的布局控件(如 TwoColumnLayout)和工具类。 --- ### Story 2.1: 实现 2xN Layout 布局控件 **As a** 控件库开发者, **I want** 创建一个专用的 2xN Layout 布局控件(左侧标签,右侧编辑器), **so that** PropertyGrid 可以使用统一的布局来呈现属性列表,且这个布局控件可以复用到其他需要"标签-值"配对的场景。 #### Acceptance Criteria 1. 在 `Penguin.AvaloniaUI/Layouts/` 下创建 `TwoColumnLayout.cs` 控件类: - 继承自 `Panel` 或使用 `Grid` 作为基础 - 支持添加多行,每行包含左侧标签(Label)和右侧内容(Content) 2. 提供简单的 API 来添加行: - 可以通过 Items 集合添加行 - 每个 Item 包含 Label(string)和 Content(Control) 3. 布局行为: - 左列(标签列)宽度固定或自适应最长标签的宽度 - 右列(内容列)占据剩余空间 - 行与行之间有合适的垂直间距(如 8px) - 标签垂直对齐到内容控件的中心或顶部 4. 响应主题系统: - 标签文本颜色使用 `TextSecondary` - 背景色透明或使用 `Surface` 5. 在 Example 中创建测试页面,演示 TwoColumnLayout 的使用: - 至少 5 行测试数据 - 包含不同类型的右侧内容(TextBox, CheckBox, ComboBox) 6. 布局在窗口缩放时应正确响应,不出现重叠或错位 --- ### Story 2.2: 实现基础属性编辑器控件 **As a** 控件库开发者, **I want** 为 PropertyGrid 支持的 6 种属性类型创建或选择合适的编辑器控件, **so that** PropertyGrid 可以根据属性类型自动选择正确的编辑器。 #### Acceptance Criteria 1. 为以下属性类型选择或创建编辑器控件: - **string**: 使用 Avalonia 的 `TextBox` - **int/double**: 使用 Avalonia 的 `NumericUpDown`(如果 Semi 或 Avalonia 提供)或自定义数字输入框 - **bool**: 使用 Avalonia 的 `CheckBox` - **enum**: 使用 Avalonia 的 `ComboBox`,Items 为枚举值列表 - **DateTime**: 使用 Avalonia 的 `DatePicker` 和 `TimePicker`(或组合控件) 2. 所有编辑器控件应响应主题系统,使用语义化颜色 3. 编辑器控件应支持基础的数据绑定: - 双向绑定(TwoWay Binding) - 支持 `INotifyPropertyChanged` 机制 4. 在 Example 中创建测试页面,演示所有 6 种编辑器: - 每种编辑器独立展示 - 显示当前绑定的值(使用 TextBlock) - 修改编辑器后,绑定的值应自动更新 5. 编辑器控件应具备基础的验证提示能力: - 依赖 Avalonia 的内置验证机制(如 DataValidationErrors) - 验证失败时显示红色边框或错误图标 --- ### Story 2.3: 实现 PropertyGrid 核心逻辑和数据模型 **As a** 控件库开发者, **I want** 定义 PropertyGrid 的数据模型和核心逻辑,支持从对象反射属性信息, **so that** PropertyGrid 可以自动生成属性列表,为后续的 UI 呈现做好准备。 #### Acceptance Criteria 1. 在 `Penguin.AvaloniaUI/Controls/PropertyGrid/` 下创建以下类: - `PropertyGrid.cs`: PropertyGrid 主控件类 - `PropertyItem.cs`: 表示单个属性的数据模型,包含: - Name(属性名称) - Value(属性值) - Type(属性类型) - IsReadOnly(是否只读) - Category(分组类别,可选) - Description(描述,可选) 2. PropertyGrid 提供 `SelectedObject` 属性(依赖属性): - 接受任意对象 - 当 SelectedObject 变化时,自动通过反射解析对象的属性 3. 反射逻辑: - 获取对象的所有 public 属性 - 过滤掉不应显示的属性(如索引器、只写属性) - 支持通过 Attribute 控制属性的显示(可选,如 `[Browsable(false)]`) 4. 将反射得到的属性转换为 `PropertyItem` 集合: - 存储在 PropertyGrid 的内部集合中 - 支持属性变化通知(使用 ReactiveUI 或 INotifyPropertyChanged) 5. 创建单元测试,验证反射逻辑: - 测试包含 6 种基础类型的测试对象 - 验证属性数量、名称、类型正确解析 - 验证只读属性标记正确识别 6. 在 Example 中创建测试页面,验证数据模型: - 定义一个包含 6 种类型属性的测试类 - 将测试对象赋值给 PropertyGrid.SelectedObject - 使用调试输出或 ListBox 显示解析出的 PropertyItem 列表(暂时不渲染为编辑器) --- ### Story 2.4: 实现 PropertyGrid UI 呈现和属性编辑 **As a** PropertyGrid 的用户(开发者), **I want** PropertyGrid 能够自动将属性列表渲染为可编辑的 UI, **so that** 我可以直接使用 PropertyGrid 控件,无需手动编写属性编辑界面。 #### Acceptance Criteria 1. PropertyGrid 使用 TwoColumnLayout 呈现属性列表: - 左列显示属性名称(PropertyItem.Name) - 右列根据属性类型显示对应的编辑器控件 2. 属性类型到编辑器的映射逻辑: - string → TextBox - int/double → NumericUpDown - bool → CheckBox - enum → ComboBox(自动填充枚举值) - DateTime → DatePicker/TimePicker 3. 编辑器控件与属性值双向绑定: - 修改编辑器时,PropertyItem.Value 自动更新 - PropertyItem.Value 变化时,编辑器自动刷新(如果 SelectedObject 外部修改) 4. 只读属性的处理: - 如果 PropertyItem.IsReadOnly = true,编辑器应禁用(IsEnabled = false)或显示为只读文本 5. 在 Example 中创建完整的 PropertyGrid 演示页面: - 定义一个包含所有 6 种类型的配置类(如 `DemoSettings`) - 使用 PropertyGrid 绑定到 DemoSettings 实例 - 在页面底部显示当前配置对象的 JSON 或字符串表示,验证属性编辑生效 6. PropertyGrid 应响应主题切换,所有编辑器控件使用主题颜色 7. PropertyGrid 的默认宽度应至少 400px,高度自适应内容(或支持滚动) --- ### Story 2.5: 实现属性分组功能 **As a** PropertyGrid 的用户(开发者), **I want** PropertyGrid 支持将属性按类别分组显示, **so that** 当属性数量较多时,配置界面更清晰易读。 #### Acceptance Criteria 1. PropertyItem 支持 Category 属性(字符串): - 如果未指定 Category,默认分组为 "General" 或不分组 2. 支持通过 Attribute 在数据模型上标记分组: - 例如使用 `[Category("Network")]` 标记属性 - 反射逻辑自动读取 Category Attribute 3. PropertyGrid 按 Category 对 PropertyItem 进行分组: - 相同 Category 的属性显示在一起 - 分组之间有视觉分隔(如分隔线或分组标题) 4. 分组标题的呈现: - 使用稍大的字体或加粗显示分组名称 - 分组标题使用 `TextPrimary` 颜色 - 分组标题上方有一定的间距(如 16px) 5. 支持可选的分组折叠功能(可选,MVP 可以暂时不实现折叠): - 如果时间允许,分组可以展开/折叠 - 默认所有分组展开 6. 在 Example 中扩展演示页面: - DemoSettings 类的属性使用 `[Category]` 标记,分为至少 2 个分组(如 "General"、"Advanced") - PropertyGrid 正确显示分组 - 验证分组标题和属性的视觉层次清晰 --- ### Story 2.6: PropertyGrid 集成测试和优化 **As a** 控件库开发者, **I want** 对 PropertyGrid 进行全面测试和性能优化, **so that** 确保 PropertyGrid 在真实场景下稳定可用,并满足性能要求(50 属性 < 200ms)。 #### Acceptance Criteria 1. 创建综合测试类,包含 50 个属性,覆盖所有支持的类型和分组 2. 在 Example 中使用该测试类验证 PropertyGrid: - PropertyGrid 正确渲染所有 50 个属性 - UI 生成时间 < 200ms(符合 NFR5) - 所有编辑器可正常交互,值绑定正确 3. 测试边缘情况: - SelectedObject 为 null 时,PropertyGrid 显示空状态或提示信息 - 对象属性在运行时变化时,PropertyGrid 能够正确响应(如果支持动态刷新) - 只读属性不能编辑 4. 主题切换测试: - 在浅色和暗色主题下,PropertyGrid 的视觉呈现正确 - 主题切换时,PropertyGrid 无闪烁或错位 5. 性能优化(如果需要): - 如果初始加载超过 200ms,使用虚拟化或延迟加载优化 - 如果属性数量超过 100,考虑使用 `VirtualizingStackPanel` 6. 修复 Example 测试中发现的所有 Bug 7. 在 README 中添加 PropertyGrid 的使用文档: - 基础用法示例(XAML 和代码) - 支持的属性类型列表 - 如何使用 Category Attribute - 已知限制(如暂不支持嵌套对象) ---