mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-23 09:48:48 +08:00
10 KiB
10 KiB
AtomUI Gallery — 编码规范摘要
文档版本:2026-04-15
1. 命名约定
| 元素 | 规范 | 示例 |
|---|---|---|
| 类名 | PascalCase | ButtonShowCase, CaseNavigationViewModel |
| 接口名 | I 前缀 + PascalCase |
IScreen, IRoutableViewModel |
| 公共属性 | PascalCase | HostScreen, ButtonSizeType |
| 私有字段 | _ 前缀 + camelCase |
_viewModel, _showCaseViewModelFactories |
| 常量 | PascalCase(const string) |
public static EntityKey ID = "Button" |
| 方法 | PascalCase | NavigateTo(), HandleMenuItemCheckChanged() |
| 事件处理方法 | Handle + 描述 |
HandleBasicModalButtonClick, HandleNavMenuItemClick |
| XAML 模板部件 | PART_ 前缀 |
PART_MainPanel, PART_RootBorder |
| 静态属性 | PascalCase + Property 后缀 |
TitleProperty, DescriptionProperty |
| ViewModel ID | PascalCase 字符串 | "Button", "AboutUs", "CustomizeTheme" |
2. 命名空间约定
| 命名空间 | 用途 |
|---|---|
AtomUIGallery |
根命名空间 |
AtomUIGallery.Desktop |
桌面启动项目 |
AtomUIGallery.ShowCases.ViewModels |
所有 ShowCase ViewModel(平铺,不按分类子命名空间) |
AtomUIGallery.ShowCases.Views |
所有 ShowCase View(平铺,不按分类子命名空间) |
AtomUIGallery.Workspace.ViewModels |
工作区 ViewModel |
AtomUIGallery.Workspace.Views |
工作区 View |
AtomUIGallery.Controls |
Gallery 自定义控件 |
AtomUIGallery.Models |
数据模型 |
AtomUIGallery.Utils |
工具类 |
AtomUIGallery.Workspace.Localization.*Lang |
本地化资源 |
AtomUIGallery.Localization |
生成的本地化基础设施 |
AtomUIGallery.ShowCases.ShowCaseControls |
ShowCase 专用控件 |
AtomUIGallery.Icons.Desktop |
图标项目 |
重要:所有 ShowCase ViewModel 使用扁平命名空间
AtomUIGallery.ShowCases.ViewModels,不管文件系统中按General/、Layout/等子目录组织。View 同理使用AtomUIGallery.ShowCases.Views。
3. 文件组织方式
3.1 ViewModel 文件
- 目录按分类组织:
ViewModels/General/、ViewModels/Layout/等 - 但命名空间始终为
AtomUIGallery.ShowCases.ViewModels - 文件名 = 类名(如
ButtonViewModel.cs) - 每个文件通常只包含一个类(
OsInfoViewModel.cs是例外,包含辅助类)
3.2 View 文件
- 目录按分类组织:
Views/General/、Views/DataEntry/等 - 命名空间始终为
AtomUIGallery.ShowCases.Views - 成对出现:
.axaml+.axaml.cs(代码后置) - ⚠️ 存在非标准文件名(历史遗留):
FormShowCase.axmal.cs(注意.axmal,不是.axaml)RateShowCase.axmal.cs(同上)TourShowCase.axmal.cs(同上)ResultShowCase.cs.axaml(注意.cs.axaml,不是.axaml)CustomizeThemeShowCase.cs(直接.cs,不是.axaml.cs)
3.3 控件文件
- 控件类 + 主题文件成对:
XxxControl.cs+XxxControlTheme.axaml - 主题提供器:
XxxThemesProvider.cs+XxxThemesProvider.axaml
4. 代码组织模式
4.1 ViewModel 标准结构
// 1. using 声明
using AtomUI.Controls;
using ReactiveUI;
// 2. 文件级命名空间
namespace AtomUIGallery.ShowCases.ViewModels;
// 3. 类定义(实现接口)
public class XxxViewModel : ReactiveObject, IRoutableViewModel
{
// 4. 静态 ID
public static EntityKey ID = "Xxx";
// 5. IRoutableViewModel 实现
public IScreen HostScreen { get; }
public string UrlPathSegment { get; } = ID.ToString();
// 6. 响应式属性(private 字段 + public 属性 + RaiseAndSetIfChanged)
private SizeType _sizeType;
public SizeType SizeType
{
get => _sizeType;
set => this.RaiseAndSetIfChanged(ref _sizeType, value);
}
// 7. 构造函数
public XxxViewModel(IScreen screen)
{
HostScreen = screen;
}
}
4.2 View 标准结构
// 1. using 声明
using AtomUIGallery.ShowCases.ViewModels;
using ReactiveUI;
using ReactiveUI.Avalonia;
// 2. 文件级命名空间
namespace AtomUIGallery.ShowCases.Views;
// 3. partial 类继承 ReactiveUserControl<TViewModel>
public partial class XxxShowCase : ReactiveUserControl<XxxViewModel>
{
// 4. 构造函数:WhenActivated + InitializeComponent
public XxxShowCase()
{
this.WhenActivated(disposables =>
{
// 5. 激活时的逻辑(事件订阅、初始化等)
});
InitializeComponent();
}
// 6. 事件处理方法
public void HandleXxxClick(object? sender, RoutedEventArgs e) { ... }
}
4.3 本地化资源标准结构
using AtomUI.Theme.Language;
using AtomUIGallery.Localization;
using AtomUIGallery.Workspace.Views;
namespace AtomUIGallery.Workspace.Localization.XxxLang;
[LanguageProvider(LanguageCode.en_US, Xxx.LanguageId)]
internal class en_US : LanguageProvider
{
public const string Key1 = "English Text";
public const string Key2 = "Another Text";
protected override Type GetResourceKindType() => typeof(XxxLangResourceKind);
}
5. AXAML 编码规范
5.1 命名空间前缀
| 前缀 | URI | 用途 |
|---|---|---|
atom |
https://atomui.net 或 using:AtomUI.Desktop.Controls |
AtomUI 控件 |
antdicons |
https://atomui.net/icons/antdesign |
Ant Design 图标 |
gallery |
https://atomui.net/oss-controls/gallery |
Gallery 控件/模型/本地化 |
rxui |
http://reactiveui.net |
ReactiveUI 控件(RoutedViewHost) |
viewmodels |
using:AtomUIGallery.ShowCases.ViewModels |
ViewModel 引用(x:Static) |
5.2 Token 资源引用
- 共享 Token:
{atom:SharedTokenResource ColorBorder} - 控件 Token:
{atom:TokenResource XxxProperty}
5.3 本地化资源引用
{gallery:CaseNavigationLangResource <Key>}{gallery:WorkspaceWindowLangResource <Key>}
5.4 静态引用
- ViewModel ID:
ItemKey="{x:Static viewmodels:ButtonViewModel.ID}" - 枚举:
Tag="{x:Static workspaceviews:WindowMenuItemKind.DarkMode}" - 模板部件:
Name="PART_MainPanel"
6. 设计模式
| 模式 | 应用场景 |
|---|---|
| MVVM | 全局架构模式(ReactiveUI) |
| 路由导航 | IScreen + RoutingState + RoutedViewHost |
| 工厂模式 | CaseNavigationViewModel._showCaseViewModelFactories(Dictionary<EntityKey, Func<IRoutableViewModel>>) |
| 观察者模式 | ReactiveObject.RaiseAndSetIfChanged + WhenActivated |
| 模板方法 | ShowCasePanel.OnApplyTemplate() 中的布局算法 |
| Provider 模式 | LanguageProvider、IconProvider、ControlThemesProvider — AtomUI 大量使用的注册机制 |
| Dispose 模式 | WhenActivated 中通过 CompositeDisposable 管理事件订阅生命周期 |
| Source Generator | 语言资源枚举、图标提供者、XAML 名称访问器 — 自动代码生成 |
| Strategy | Dark/Light/Compact 主题模式切换 |
7. 事件处理模式
ShowCase View 中的事件处理有两种模式:
模式 A:Code-Behind 事件处理(当前主流)
// 在 AXAML 中绑定:<Button Click="HandleLoadingBtnClick"/>
public void HandleLoadingBtnClick(object? sender, RoutedEventArgs args)
{
if (sender is Button button)
{
button.IsLoading = true;
Dispatcher.UIThread.InvokeAsync(async () =>
{
await Task.Delay(TimeSpan.FromSeconds(3));
button.IsLoading = false;
});
}
}
模式 B:ViewModel 属性绑定
// ViewModel 中定义响应式属性
private SizeType _buttonSizeType;
public SizeType ButtonSizeType
{
get => _buttonSizeType;
set => this.RaiseAndSetIfChanged(ref _buttonSizeType, value);
}
// View 中通过 DataContext 设置
_viewModel.ButtonSizeType = SizeType.Large;
当前状态:大多数 ShowCase 使用模式 A(Code-Behind 直接操作控件),少数使用模式 B。Gallery 是演示项目,Code-Behind 操作控件是合理的选择。
8. ReactiveUI 使用规范
8.1 属性变更通知
使用 RaiseAndSetIfChanged 而非 INotifyPropertyChanged:
// ✅ 正确
private SizeType _sizeType;
public SizeType SizeType
{
get => _sizeType;
set => this.RaiseAndSetIfChanged(ref _sizeType, value);
}
8.2 WhenActivated + DisposeWith
在 View 构造函数中注册 WhenActivated,通过 DisposeWith 或 Disposable.Create 管理订阅生命周期:
this.WhenActivated(disposables =>
{
// 方式 1:DisposeWith
this.WhenAnyValue(x => x.ViewModel!.SearchText)
.Subscribe(text => FilterIcons(text))
.DisposeWith(disposables);
// 方式 2:Disposable.Create(用于事件订阅)
MyButton.Click += HandleClick;
disposables.Add(Disposable.Create(() => MyButton.Click -= HandleClick));
});
8.3 路由规范
- 每个 ViewModel 必须实现
IRoutableViewModel HostScreen引用传入的IScreen实例UrlPathSegment使用ID.ToString()作为路由标识
9. AXAML ShowCase 根元素模板
<!-- ShowCase View 的 AXAML 根元素标准结构 -->
<rxui:ReactiveUserControl
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:rxui="http://reactiveui.net"
xmlns:atom="https://atomui.net"
xmlns:gallery="https://atomui.net/oss-controls/gallery"
xmlns:vm="using:AtomUIGallery.ShowCases.ViewModels"
x:TypeArguments="vm:XxxViewModel"
x:Class="AtomUIGallery.ShowCases.Views.XxxShowCase">
<gallery:ShowCasePanel>
<gallery:ShowCaseItem Title="基本用法" Description="...">
<!-- 控件演示内容 -->
</gallery:ShowCaseItem>
</gallery:ShowCasePanel>
</rxui:ReactiveUserControl>
7. 异常处理
- 全局异常:
Program.Main()包裹 try-catch,异常写入AppCrashLogs/CrashLog_*.log - 局部异常:极少使用 try-catch,主要在
SystemInfoProvider(硬件信息获取)和LinuxDistributionDetector(文件系统读取)中 - 空安全:全局启用
<Nullable>enable</Nullable>,广泛使用?.和is模式匹配
8. 编译器设置
| 设置 | 值 |
|---|---|
<Nullable> |
enable |
<EmitCompilerGeneratedFiles> |
true(输出到 GeneratedFiles/) |
<TargetFrameworks> |
$(AtomUITargetFrameworks) — Debug: net10.0 / Release: net10.0;net8.0 |
| Avalonia 名称生成器 | 自动为 x:Name 生成强类型字段 |
| AtomUI Generator | 生成 LanguageResourceConst、LanguageProviderPool、TokenResourceConst |