diff --git a/AuroraDesk.Infrastructure/Services/NavigationService.cs b/AuroraDesk.Infrastructure/Services/NavigationService.cs
index d8f29eb..b269494 100644
--- a/AuroraDesk.Infrastructure/Services/NavigationService.cs
+++ b/AuroraDesk.Infrastructure/Services/NavigationService.cs
@@ -253,6 +253,13 @@ public class NavigationService : INavigationService
ViewModel = _pageViewModelFactory.CreatePageViewModel("livecharts2", screen)
}
}
+ },
+ new NavigationItem
+ {
+ Id = "form",
+ Title = "表单示例",
+ IconType = IconType.DocumentText,
+ ViewModel = _pageViewModelFactory.CreatePageViewModel("form", screen)
}
};
diff --git a/AuroraDesk.Presentation/Converters/StringConverters.cs b/AuroraDesk.Presentation/Converters/StringConverters.cs
index 4c19eb6..5a528cf 100644
--- a/AuroraDesk.Presentation/Converters/StringConverters.cs
+++ b/AuroraDesk.Presentation/Converters/StringConverters.cs
@@ -45,6 +45,16 @@ public static class StringConverters
/// 整数到可见性的转换器(0 则不可见)
///
public static readonly IValueConverter IntToVisibilityConverter = new IntToVisibilityConverter();
+
+ ///
+ /// 字符串非空检查转换器(非空则返回 true)
+ ///
+ public static readonly IValueConverter IsNotNullOrEmptyConverter = new IsNotNullOrEmptyConverter();
+
+ ///
+ /// 布尔值到可见性转换器
+ ///
+ public static readonly IValueConverter BoolToVisibilityConverter = new BoolToVisibilityConverter();
}
///
@@ -212,3 +222,48 @@ public class IntToVisibilityConverter : IValueConverter
throw new NotImplementedException();
}
}
+
+///
+/// 字符串非空检查转换器(非空则返回 true)
+///
+public class IsNotNullOrEmptyConverter : IValueConverter
+{
+ public static IsNotNullOrEmptyConverter Instance { get; } = new();
+
+ public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ return !string.IsNullOrEmpty(value?.ToString());
+ }
+
+ public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+}
+
+///
+/// 布尔值到可见性转换器
+///
+public class BoolToVisibilityConverter : IValueConverter
+{
+ public static BoolToVisibilityConverter Instance { get; } = new();
+
+ public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ if (value is bool boolValue)
+ {
+ // 如果 parameter 是 "Invert",则反转布尔值
+ if (parameter?.ToString() == "Invert")
+ {
+ return !boolValue;
+ }
+ return boolValue;
+ }
+ return false;
+ }
+
+ public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+}
diff --git a/AuroraDesk.Presentation/Extensions/ServiceCollectionExtensions.cs b/AuroraDesk.Presentation/Extensions/ServiceCollectionExtensions.cs
index f2252b1..abb474e 100644
--- a/AuroraDesk.Presentation/Extensions/ServiceCollectionExtensions.cs
+++ b/AuroraDesk.Presentation/Extensions/ServiceCollectionExtensions.cs
@@ -55,6 +55,7 @@ public static class ServiceCollectionExtensions
services.AddTransient();
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
// 注意:MainWindowViewModel 的注册移到主项目的 App.axaml.cs 中
// 因为它依赖 AppViewModel,而 AppViewModel 在 AddReactiveUI() 中注册
diff --git a/AuroraDesk.Presentation/Services/PageViewModelFactory.cs b/AuroraDesk.Presentation/Services/PageViewModelFactory.cs
index 0c179a1..d3eaa51 100644
--- a/AuroraDesk.Presentation/Services/PageViewModelFactory.cs
+++ b/AuroraDesk.Presentation/Services/PageViewModelFactory.cs
@@ -66,6 +66,7 @@ public class PageViewModelFactory : IPageViewModelFactory
"wireless-adapter" => CreateWirelessAdapterPageViewModel(screen),
"scottplot" => CreatePageViewModel(screen),
"livecharts2" => CreatePageViewModel(screen),
+ "form" => CreatePageViewModel(screen),
_ => throw new ArgumentException($"Unknown page: {pageId}", nameof(pageId))
};
}
diff --git a/AuroraDesk.Presentation/ViewModels/Pages/FormPageViewModel.cs b/AuroraDesk.Presentation/ViewModels/Pages/FormPageViewModel.cs
new file mode 100644
index 0000000..68c14f2
--- /dev/null
+++ b/AuroraDesk.Presentation/ViewModels/Pages/FormPageViewModel.cs
@@ -0,0 +1,458 @@
+using AuroraDesk.Presentation.ViewModels.Base;
+using ReactiveUI;
+using System.Collections.ObjectModel;
+using System.Reactive;
+
+namespace AuroraDesk.Presentation.ViewModels.Pages;
+
+///
+/// 表单类型枚举
+///
+public enum FormType
+{
+ Basic, // 基础表单(垂直布局,全字段)
+ Simple, // 简洁表单(水平布局,标签和输入框一行)
+ Contact, // 联系表单(包含下拉框选择)
+ Feedback, // 反馈表单(包含复选框)
+ Register // 注册表单(两列布局)
+}
+
+///
+/// 表单页面 ViewModel
+///
+public class FormPageViewModel : RoutableViewModel
+{
+ private bool _isFormDialogOpen;
+ private FormType _currentFormType = FormType.Basic;
+ private string _formTitle = "填写表单";
+ private string _formDescription = "请填写以下信息";
+ private string _name = string.Empty;
+ private string _email = string.Empty;
+ private string _phone = string.Empty;
+ private string _address = string.Empty;
+ private string _remarks = string.Empty;
+ private string _submitResult = string.Empty;
+ private string _selectedCountry = string.Empty;
+ private string _selectedCity = string.Empty;
+ private bool _agreeTerms = false;
+ private bool _subscribeNewsletter = false;
+ private bool _receiveNotifications = false;
+
+ ///
+ /// 构造函数
+ ///
+ /// 宿主 Screen
+ public FormPageViewModel(IScreen hostScreen) : base(hostScreen, "Form")
+ {
+ // 初始化下拉框选项
+ Countries = new ObservableCollection { "中国", "美国", "日本", "韩国", "英国", "德国", "法国", "其他" };
+ Cities = new ObservableCollection { "北京", "上海", "广州", "深圳", "杭州", "成都", "其他" };
+
+ ShowBasicFormCommand = ReactiveCommand.Create(() => ShowForm(FormType.Basic));
+ ShowSimpleFormCommand = ReactiveCommand.Create(() => ShowForm(FormType.Simple));
+ ShowContactFormCommand = ReactiveCommand.Create(() => ShowForm(FormType.Contact));
+ ShowFeedbackFormCommand = ReactiveCommand.Create(() => ShowForm(FormType.Feedback));
+ ShowRegisterFormCommand = ReactiveCommand.Create(() => ShowForm(FormType.Register));
+ SubmitFormCommand = ReactiveCommand.Create(SubmitForm);
+ CancelFormCommand = ReactiveCommand.Create(CancelForm);
+ }
+
+ ///
+ /// 是否显示表单对话框
+ ///
+ public bool IsFormDialogOpen
+ {
+ get => _isFormDialogOpen;
+ set => this.RaiseAndSetIfChanged(ref _isFormDialogOpen, value);
+ }
+
+ ///
+ /// 当前表单类型
+ ///
+ public FormType CurrentFormType
+ {
+ get => _currentFormType;
+ set => this.RaiseAndSetIfChanged(ref _currentFormType, value);
+ }
+
+ ///
+ /// 表单标题
+ ///
+ public string FormTitle
+ {
+ get => _formTitle;
+ set => this.RaiseAndSetIfChanged(ref _formTitle, value);
+ }
+
+ ///
+ /// 表单描述
+ ///
+ public string FormDescription
+ {
+ get => _formDescription;
+ set => this.RaiseAndSetIfChanged(ref _formDescription, value);
+ }
+
+ ///
+ /// 是否显示电话字段
+ ///
+ public bool ShowPhoneField => CurrentFormType == FormType.Basic ||
+ CurrentFormType == FormType.Contact ||
+ CurrentFormType == FormType.Register;
+
+ ///
+ /// 是否显示地址字段
+ ///
+ public bool ShowAddressField => CurrentFormType == FormType.Basic ||
+ CurrentFormType == FormType.Register;
+
+ ///
+ /// 是否显示备注字段
+ ///
+ public bool ShowRemarksField => CurrentFormType == FormType.Basic ||
+ CurrentFormType == FormType.Feedback;
+
+ ///
+ /// 是否使用水平布局(标签和输入框在一行)
+ ///
+ public bool UseHorizontalLayout => CurrentFormType == FormType.Simple;
+
+ ///
+ /// 是否使用两列布局
+ ///
+ public bool UseTwoColumnLayout => CurrentFormType == FormType.Register;
+
+ ///
+ /// 是否显示下拉框字段
+ ///
+ public bool ShowComboBoxFields => CurrentFormType == FormType.Contact;
+
+ ///
+ /// 是否显示复选框字段
+ ///
+ public bool ShowCheckBoxFields => CurrentFormType == FormType.Feedback;
+
+ ///
+ /// 国家列表
+ ///
+ public ObservableCollection Countries { get; }
+
+ ///
+ /// 城市列表
+ ///
+ public ObservableCollection Cities { get; }
+
+ ///
+ /// 选中的国家
+ ///
+ public string SelectedCountry
+ {
+ get => _selectedCountry;
+ set => this.RaiseAndSetIfChanged(ref _selectedCountry, value);
+ }
+
+ ///
+ /// 选中的城市
+ ///
+ public string SelectedCity
+ {
+ get => _selectedCity;
+ set => this.RaiseAndSetIfChanged(ref _selectedCity, value);
+ }
+
+ ///
+ /// 同意条款
+ ///
+ public bool AgreeTerms
+ {
+ get => _agreeTerms;
+ set => this.RaiseAndSetIfChanged(ref _agreeTerms, value);
+ }
+
+ ///
+ /// 订阅 newsletter
+ ///
+ public bool SubscribeNewsletter
+ {
+ get => _subscribeNewsletter;
+ set => this.RaiseAndSetIfChanged(ref _subscribeNewsletter, value);
+ }
+
+ ///
+ /// 接收通知
+ ///
+ public bool ReceiveNotifications
+ {
+ get => _receiveNotifications;
+ set => this.RaiseAndSetIfChanged(ref _receiveNotifications, value);
+ }
+
+ ///
+ /// 姓名
+ ///
+ public string Name
+ {
+ get => _name;
+ set => this.RaiseAndSetIfChanged(ref _name, value);
+ }
+
+ ///
+ /// 邮箱
+ ///
+ public string Email
+ {
+ get => _email;
+ set => this.RaiseAndSetIfChanged(ref _email, value);
+ }
+
+ ///
+ /// 电话
+ ///
+ public string Phone
+ {
+ get => _phone;
+ set => this.RaiseAndSetIfChanged(ref _phone, value);
+ }
+
+ ///
+ /// 地址
+ ///
+ public string Address
+ {
+ get => _address;
+ set => this.RaiseAndSetIfChanged(ref _address, value);
+ }
+
+ ///
+ /// 备注
+ ///
+ public string Remarks
+ {
+ get => _remarks;
+ set => this.RaiseAndSetIfChanged(ref _remarks, value);
+ }
+
+ ///
+ /// 提交结果
+ ///
+ public string SubmitResult
+ {
+ get => _submitResult;
+ set => this.RaiseAndSetIfChanged(ref _submitResult, value);
+ }
+
+ ///
+ /// 显示基础表单命令
+ ///
+ public ReactiveCommand ShowBasicFormCommand { get; }
+
+ ///
+ /// 显示简洁表单命令
+ ///
+ public ReactiveCommand ShowSimpleFormCommand { get; }
+
+ ///
+ /// 显示联系表单命令
+ ///
+ public ReactiveCommand ShowContactFormCommand { get; }
+
+ ///
+ /// 显示反馈表单命令
+ ///
+ public ReactiveCommand ShowFeedbackFormCommand { get; }
+
+ ///
+ /// 显示注册表单命令
+ ///
+ public ReactiveCommand ShowRegisterFormCommand { get; }
+
+ ///
+ /// 提交表单命令
+ ///
+ public ReactiveCommand SubmitFormCommand { get; }
+
+ ///
+ /// 取消表单命令
+ ///
+ public ReactiveCommand CancelFormCommand { get; }
+
+ private void ShowForm(FormType formType)
+ {
+ // 重置表单数据
+ Name = string.Empty;
+ Email = string.Empty;
+ Phone = string.Empty;
+ Address = string.Empty;
+ Remarks = string.Empty;
+ SelectedCountry = string.Empty;
+ SelectedCity = string.Empty;
+ AgreeTerms = false;
+ SubscribeNewsletter = false;
+ ReceiveNotifications = false;
+ SubmitResult = string.Empty;
+
+ // 设置表单类型
+ CurrentFormType = formType;
+
+ // 根据表单类型设置标题和描述
+ switch (formType)
+ {
+ case FormType.Basic:
+ FormTitle = "基础表单";
+ FormDescription = "垂直布局,标签在上输入框在下";
+ break;
+ case FormType.Simple:
+ FormTitle = "简洁表单";
+ FormDescription = "水平布局,标签和输入框在同一行";
+ break;
+ case FormType.Contact:
+ FormTitle = "联系表单";
+ FormDescription = "包含下拉框选择国家/城市";
+ break;
+ case FormType.Feedback:
+ FormTitle = "反馈表单";
+ FormDescription = "包含复选框选项";
+ break;
+ case FormType.Register:
+ FormTitle = "注册表单";
+ FormDescription = "两列布局,充分利用空间";
+ break;
+ }
+
+ // 触发所有属性更新
+ this.RaisePropertyChanged(nameof(ShowPhoneField));
+ this.RaisePropertyChanged(nameof(ShowAddressField));
+ this.RaisePropertyChanged(nameof(ShowRemarksField));
+ this.RaisePropertyChanged(nameof(UseHorizontalLayout));
+ this.RaisePropertyChanged(nameof(UseTwoColumnLayout));
+ this.RaisePropertyChanged(nameof(ShowComboBoxFields));
+ this.RaisePropertyChanged(nameof(ShowCheckBoxFields));
+
+ // 显示对话框
+ IsFormDialogOpen = true;
+ }
+
+ private void SubmitForm()
+ {
+ // 验证必填字段
+ if (string.IsNullOrWhiteSpace(Name))
+ {
+ SubmitResult = "错误:姓名不能为空";
+ return;
+ }
+
+ if (string.IsNullOrWhiteSpace(Email))
+ {
+ SubmitResult = "错误:邮箱不能为空";
+ return;
+ }
+
+ // 简单的邮箱格式验证
+ if (!Email.Contains("@") || !Email.Contains("."))
+ {
+ SubmitResult = "错误:邮箱格式不正确";
+ return;
+ }
+
+ // 根据表单类型验证特定字段
+ if (CurrentFormType == FormType.Contact || CurrentFormType == FormType.Register)
+ {
+ if (string.IsNullOrWhiteSpace(Phone))
+ {
+ SubmitResult = "错误:电话不能为空";
+ return;
+ }
+ }
+
+ if (CurrentFormType == FormType.Register)
+ {
+ if (string.IsNullOrWhiteSpace(Address))
+ {
+ SubmitResult = "错误:地址不能为空";
+ return;
+ }
+ }
+
+ if (CurrentFormType == FormType.Feedback)
+ {
+ if (string.IsNullOrWhiteSpace(Remarks))
+ {
+ SubmitResult = "错误:反馈内容不能为空";
+ return;
+ }
+ if (!AgreeTerms)
+ {
+ SubmitResult = "错误:必须同意服务条款";
+ return;
+ }
+ }
+
+ if (CurrentFormType == FormType.Contact)
+ {
+ if (string.IsNullOrWhiteSpace(SelectedCountry))
+ {
+ SubmitResult = "错误:请选择国家";
+ return;
+ }
+ if (string.IsNullOrWhiteSpace(SelectedCity))
+ {
+ SubmitResult = "错误:请选择城市";
+ return;
+ }
+ }
+
+ // 关闭对话框
+ IsFormDialogOpen = false;
+
+ // 显示提交结果
+ var formTypeName = CurrentFormType switch
+ {
+ FormType.Basic => "基础表单",
+ FormType.Simple => "简洁表单",
+ FormType.Contact => "联系表单",
+ FormType.Feedback => "反馈表单",
+ FormType.Register => "注册表单",
+ _ => "表单"
+ };
+
+ var result = $"[{formTypeName}] 提交成功!\n姓名:{Name}\n邮箱:{Email}";
+ if (ShowPhoneField && !string.IsNullOrWhiteSpace(Phone))
+ {
+ result += $"\n电话:{Phone}";
+ }
+ if (ShowAddressField && !string.IsNullOrWhiteSpace(Address))
+ {
+ result += $"\n地址:{Address}";
+ }
+ if (ShowComboBoxFields)
+ {
+ if (!string.IsNullOrWhiteSpace(SelectedCountry))
+ {
+ result += $"\n国家:{SelectedCountry}";
+ }
+ if (!string.IsNullOrWhiteSpace(SelectedCity))
+ {
+ result += $"\n城市:{SelectedCity}";
+ }
+ }
+ if (ShowRemarksField && !string.IsNullOrWhiteSpace(Remarks))
+ {
+ result += $"\n备注:{Remarks}";
+ }
+ if (ShowCheckBoxFields)
+ {
+ result += $"\n同意条款:{(AgreeTerms ? "是" : "否")}";
+ result += $"\n订阅邮件:{(SubscribeNewsletter ? "是" : "否")}";
+ result += $"\n接收通知:{(ReceiveNotifications ? "是" : "否")}";
+ }
+
+ SubmitResult = result;
+ }
+
+ private void CancelForm()
+ {
+ IsFormDialogOpen = false;
+ SubmitResult = "已取消提交";
+ }
+}
+
diff --git a/AuroraDesk.Presentation/Views/Pages/FormPageView.axaml b/AuroraDesk.Presentation/Views/Pages/FormPageView.axaml
new file mode 100644
index 0000000..49ae09f
--- /dev/null
+++ b/AuroraDesk.Presentation/Views/Pages/FormPageView.axaml
@@ -0,0 +1,389 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AuroraDesk.Presentation/Views/Pages/FormPageView.axaml.cs b/AuroraDesk.Presentation/Views/Pages/FormPageView.axaml.cs
new file mode 100644
index 0000000..3fdbe46
--- /dev/null
+++ b/AuroraDesk.Presentation/Views/Pages/FormPageView.axaml.cs
@@ -0,0 +1,22 @@
+using Avalonia.Markup.Xaml;
+using AuroraDesk.Presentation.ViewModels.Pages;
+using ReactiveUI.Avalonia;
+
+namespace AuroraDesk.Presentation.Views.Pages;
+
+///
+/// 表单页面视图
+///
+public partial class FormPageView : ReactiveUserControl
+{
+ public FormPageView()
+ {
+ InitializeComponent();
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}
+
diff --git a/modify.md b/modify.md
index 68054a3..85ba820 100644
--- a/modify.md
+++ b/modify.md
@@ -2213,8 +2213,149 @@
- 直接更新 `Values` 集合(`ObservableCollection`),实现平滑的叠加效果
- 使用 `CreateLineSeries()` 方法创建系列,`UpdateLineChartData()` 只更新数据
- 避免整个图表重新渲染,实现真正的叠加动画效果
- - **阈值颜色区分**:
- - 使用 `LineSeries` 显示折线,保持点的位置关系
- - 使用 `ScatterSeries` 显示点,支持不同颜色
- - 超过阈值的点显示为绿色,正常点显示为蓝色/红色
- - 阈值改变时自动更新图表颜色
+ - **阈值颜色区分**:
+ - 使用 `LineSeries` 显示折线,保持点的位置关系
+ - 使用 `ScatterSeries` 显示点,支持不同颜色
+ - 超过阈值的点显示为绿色,正常点显示为蓝色/红色
+ - 阈值改变时自动更新图表颜色
+
+### 新增表单示例页面
+- **日期**: 2025年1月
+- **功能描述**: 添加了表单示例页面,包含按钮点击弹出表单对话框功能
+- **实现内容**:
+ 1. **ViewModel 层**:
+ - 创建 `FormPageViewModel`,继承自 `RoutableViewModel`
+ - 实现表单字段属性:姓名、邮箱、电话、地址、备注
+ - 实现表单对话框显示/隐藏控制:`IsFormDialogOpen`
+ - 提供表单提交和取消命令:`ShowFormCommand`、`SubmitFormCommand`、`CancelFormCommand`
+ - 实现表单验证逻辑:必填字段检查、邮箱格式验证
+ - 显示提交结果信息
+ 2. **View 层**:
+ - 创建 `FormPageView.axaml`,使用 `DialogHost` 实现弹出表单
+ - 主界面包含"打开表单"按钮和结果显示区域
+ - 表单对话框包含:
+ - 标题区域(带图标)
+ - 表单字段:姓名(必填)、邮箱(必填)、电话(可选)、地址(可选)、备注(可选)
+ - 错误提示区域(动态显示验证错误)
+ - 提交和取消按钮
+ - 表单支持滚动,适配长内容
+ 3. **转换器扩展**:
+ - 在 `StringConverters` 中新增 `IsNotNullOrEmptyConverter` 转换器
+ - 用于检查字符串是否非空,控制错误提示区域的显示
+ 4. **服务注册**:
+ - 在 `PageViewModelFactory` 中注册 `form` 页面 ID
+ - 在 `ServiceCollectionExtensions` 中注册 `FormPageViewModel`
+ - 在 `NavigationService` 中添加"表单示例"导航项,使用 `IconType.DocumentText` 图标
+- **涉及文件**:
+ - `AuroraDesk.Presentation/ViewModels/Pages/FormPageViewModel.cs` - ViewModel
+ - `AuroraDesk.Presentation/Views/Pages/FormPageView.axaml` - 视图 XAML
+ - `AuroraDesk.Presentation/Views/Pages/FormPageView.axaml.cs` - 视图代码后台
+ - `AuroraDesk.Presentation/Converters/StringConverters.cs` - 新增转换器
+ - `AuroraDesk.Presentation/Services/PageViewModelFactory.cs` - 页面工厂注册
+ - `AuroraDesk.Presentation/Extensions/ServiceCollectionExtensions.cs` - ViewModel 注册
+ - `AuroraDesk.Infrastructure/Services/NavigationService.cs` - 导航服务
+- **技术特点**:
+ - ✅ 使用 ReactiveUI + MVVM 模式
+ - ✅ 使用 DialogHost.Avalonia 实现模态对话框
+ - ✅ 支持表单验证和错误提示
+ - ✅ 现代化的界面设计,表单布局清晰
+ - ✅ 支持必填字段和可选字段
+ - ✅ 提交结果显示在主界面
+- **效果**:
+ - ✅ 可以在导航栏中访问"表单示例"页面
+ - ✅ 点击"打开表单"按钮弹出表单对话框
+ - ✅ 填写表单信息并提交,支持验证
+ - ✅ 提交结果显示在主界面
+ - ✅ 表单界面美观,交互流畅
+
+### 扩展表单示例页面 - 支持多种表单形态
+- **日期**: 2025年1月
+- **功能描述**: 扩展表单页面,添加多个按钮,每个按钮对应不同的表单形态
+- **实现内容**:
+ 1. **表单类型枚举**:
+ - 新增 `FormType` 枚举,定义5种表单类型:
+ - `Basic`: 基础表单(全字段:姓名、邮箱、电话、地址、备注)
+ - `Simple`: 简洁表单(仅姓名、邮箱)
+ - `Contact`: 联系表单(姓名、电话、邮箱)
+ - `Feedback`: 反馈表单(姓名、邮箱、备注)
+ - `Register`: 注册表单(姓名、邮箱、电话、地址)
+ 2. **ViewModel 扩展**:
+ - 添加 `CurrentFormType` 属性,标识当前表单类型
+ - 添加 `FormTitle` 和 `FormDescription` 属性,动态显示表单标题和描述
+ - 添加字段可见性属性:`ShowPhoneField`、`ShowAddressField`、`ShowRemarksField`
+ - 添加5个不同的命令:`ShowBasicFormCommand`、`ShowSimpleFormCommand`、`ShowContactFormCommand`、`ShowFeedbackFormCommand`、`ShowRegisterFormCommand`
+ - 根据表单类型动态设置标题、描述和字段可见性
+ - 根据表单类型进行不同的验证规则
+ 3. **View 扩展**:
+ - 添加5个不同颜色的按钮,每个按钮对应一种表单类型
+ - 按钮颜色区分:基础表单(蓝色)、简洁表单(绿色)、联系表单(紫色)、反馈表单(橙色)、注册表单(红色)
+ - 表单字段根据 `IsVisible` 绑定动态显示/隐藏
+ - 表单标题和描述绑定到 ViewModel 属性,动态更新
+ 4. **验证逻辑优化**:
+ - 基础表单:验证姓名和邮箱
+ - 简洁表单:验证姓名和邮箱
+ - 联系表单:验证姓名、邮箱和电话
+ - 反馈表单:验证姓名、邮箱和备注
+ - 注册表单:验证姓名、邮箱、电话和地址
+- **涉及文件**:
+ - `AuroraDesk.Presentation/ViewModels/Pages/FormPageViewModel.cs` - 扩展 ViewModel,添加表单类型和多个命令
+ - `AuroraDesk.Presentation/Views/Pages/FormPageView.axaml` - 添加多个按钮,动态显示字段
+- **技术特点**:
+ - ✅ 使用枚举定义表单类型,类型安全
+ - ✅ 根据表单类型动态显示/隐藏字段
+ - ✅ 不同表单类型使用不同的验证规则
+ - ✅ 按钮使用不同颜色区分,视觉清晰
+ - ✅ 表单标题和描述动态更新
+- **效果**:
+ - ✅ 提供5种不同的表单形态,满足不同场景需求
+ - ✅ 点击不同按钮打开对应类型的表单
+ - ✅ 表单字段根据类型动态显示,界面简洁
+ - ✅ 每种表单类型有独立的验证规则
+ - ✅ 提交结果显示表单类型,便于区分
+
+### 重构表单示例页面 - 实现不同布局形态和控件类型
+- **日期**: 2025年1月
+- **功能描述**: 重构表单页面,为不同表单类型设计不同的布局形态和控件组合,使每种表单在视觉和功能上都有明显区别
+- **实现内容**:
+ 1. **布局形态设计**:
+ - **基础表单**:垂直布局(标签在上,输入框在下),包含所有字段
+ - **简洁表单**:水平布局(标签和输入框在同一行,使用 Grid 两列),仅包含姓名和邮箱
+ - **联系表单**:垂直布局,包含下拉框(ComboBox)选择国家和城市
+ - **反馈表单**:垂直布局,包含复选框(CheckBox)选项
+ - **注册表单**:两列布局(使用 Grid 两列两行),充分利用空间
+ 2. **新增控件类型**:
+ - **下拉框(ComboBox)**:用于联系表单,选择国家和城市
+ - **复选框(CheckBox)**:用于反馈表单,包含"同意条款"、"订阅邮件"、"接收通知"等选项
+ 3. **ViewModel 扩展**:
+ - 添加布局控制属性:`UseHorizontalLayout`、`UseTwoColumnLayout`
+ - 添加控件显示属性:`ShowComboBoxFields`、`ShowCheckBoxFields`
+ - 添加下拉框数据:`Countries`、`Cities`、`SelectedCountry`、`SelectedCity`
+ - 添加复选框数据:`AgreeTerms`、`SubscribeNewsletter`、`ReceiveNotifications`
+ - 根据表单类型进行不同的验证规则(包括下拉框和复选框验证)
+ 4. **转换器扩展**:
+ - 新增 `BoolToVisibilityConverter` 转换器,支持布尔值到可见性转换
+ - 支持反转参数(`ConverterParameter='Invert'`),用于条件显示
+ 5. **XAML 布局重构**:
+ - 使用条件显示(`IsVisible` 绑定)实现不同布局
+ - 基础表单:垂直 StackPanel 布局
+ - 简洁表单:Grid 水平布局(标签列宽 100,输入框自适应)
+ - 注册表单:Grid 两列两行布局
+ - 联系表单:在垂直布局中添加 ComboBox
+ - 反馈表单:在垂直布局中添加 CheckBox
+- **涉及文件**:
+ - `AuroraDesk.Presentation/ViewModels/Pages/FormPageViewModel.cs` - 扩展 ViewModel,添加布局控制和控件数据
+ - `AuroraDesk.Presentation/Views/Pages/FormPageView.axaml` - 重构布局,实现不同表单形态
+ - `AuroraDesk.Presentation/Converters/StringConverters.cs` - 新增 BoolToVisibilityConverter
+- **技术特点**:
+ - ✅ 5种不同的布局形态,视觉差异明显
+ - ✅ 使用 Grid 实现水平布局和两列布局
+ - ✅ 使用 ComboBox 和 CheckBox 丰富表单控件类型
+ - ✅ 条件显示实现布局切换,代码清晰
+ - ✅ 每种表单类型有独特的布局和控件组合
+- **效果**:
+ - ✅ 基础表单:传统垂直布局,标签在上输入框在下
+ - ✅ 简洁表单:水平布局,标签和输入框在同一行,节省空间
+ - ✅ 联系表单:包含下拉框选择,交互更友好
+ - ✅ 反馈表单:包含复选框选项,支持多选
+ - ✅ 注册表单:两列布局,充分利用横向空间
+ - ✅ 每种表单形态在视觉和功能上都有明显区别