Files
AtomUI/docs/Gallery/03-ShowCaseSystem.md
chinboy 7df3f29065 docs: 添加 AtomUIGallery 项目全面分析文档
- 00-Index: 文档索引与快速导航
- 01-Overview: 项目概览、目录树、依赖关系、构建运行
- 02-Architecture: MVVM架构、模块划分、核心类职责(含Mermaid图)
- 03-ShowCaseSystem: 72个ShowCase清单、路由注册、布局系统
- 04-WorkspaceSystem: 主窗口、导航面板、菜单系统
- 05-LocalizationSystem: LanguageProvider+Source Generator架构
- 06-IconSystem: IconProvider+Source Generator架构
- 07-TechStack: 技术栈清单(C#/Avalonia/ReactiveUI等)
- 08-CodingConventions: 编码规范与ReactiveUI使用规范
- 09-RisksAndNotes: 风险、技术债、迭代检查清单
2026-04-14 17:45:49 +08:00

13 KiB
Raw Permalink Blame History

ShowCase 体系详解

1. 概述

ShowCase 是 Gallery 的核心展示单元,每个 ShowCase 对应一个 AtomUI 控件的演示页面。当前共有 72 个 ShowCase,按功能分为 6 大类。

2. ShowCase 分类清单

2.1 General(通用)— 9 个

ViewModel View 控件
AboutUsViewModel AboutUsPage 关于页面(非控件)
ButtonViewModel ButtonShowCase Button 按钮
FloatButtonViewModel FloatButtonShowCase FloatButton 悬浮按钮
SplitButtonViewModel SplitButtonShowCase SplitButton 分割按钮
SeparatorViewModel SeparatorShowCase Separator 分割线
IconViewModel IconShowCase Icons 图标
PaletteViewModel PaletteShowCase Palette 调色板
OsInfoViewModel OsInfoPage 系统信息(非控件)
CustomizeThemeViewModel CustomizeThemeShowCase CustomizeTheme 主题定制

2.2 Layout(布局)— 5 个

ViewModel View 控件
BoxPanelViewModel BoxPanelShowCase BoxPanel 盒子布局(已废弃)
FlexPanelViewModel FlexPanelShowCase FlexPanel 弹性布局
GridViewModel GridShowCase Grid 栅格布局
SpaceViewModel SpaceShowCase Space 间距
SplitterViewModel SplitterShowCase Splitter 分隔面板

2.3 Navigation(导航)— 8 个

ViewModel View 控件
BreadcrumbViewModel BreadcrumbShowCase Breadcrumb 面包屑
ComboBoxViewModel ComboBoxShowCase ComboBox 组合框
DropdownButtonViewModel DropdownButtonShowCase DropdownButton 下拉菜单
ButtonSpinnerViewModel ButtonSpinnerShowCase ButtonSpinner 选项按钮
MenuViewModel MenuShowCase Menu 菜单
PaginationViewModel PaginationShowCase Pagination 分页
StepsViewModel StepsShowCase Steps 步骤条
TabControlViewModel TabControlShowCase TabControl 标签页

2.4 DataEntry(数据录入)— 18 个

ViewModel View 控件
AutoCompleteViewModel AutoCompleteShowCase AutoComplete 自动完成
CascaderViewModel CascaderShowCase Cascader 级联选择
CheckBoxViewModel CheckBoxShowCase CheckBox 多选框
ColorPickerViewModel ColorPickerShowCase ColorPicker 颜色选择器
LineEditViewModel LineEditShowCase LineEdit 输入框
DatePickerViewModel DatePickerShowCase DatePicker 日期选择器
TimePickerViewModel TimePickerShowCase TimePicker 时间选择器
FormViewModel FormShowCase Form 表单
MentionsViewModel MentionsShowCase Mentions 提及
NumberUpDownViewModel NumberUpDownShowCase NumberUpDown 数字输入框
RadioButtonViewModel RadioButtonShowCase RadioButton 单选框
RateViewModel RateShowCase Rate 评分
ToggleSwitchViewModel ToggleSwitchShowCase ToggleSwitch 开关
SelectViewModel SelectShowCase Select 选择器
SliderViewModel SliderShowCase Slider 滑动输入条
TransferViewModel TransferShowCase Transfer 穿梭框
TreeSelectViewModel TreeSelectShowCase TreeSelect 树选择
UploadViewModel UploadShowCase Upload 上传

2.5 DataDisplay(数据展示)— 21 个

ViewModel View 控件
AvatarViewModel AvatarShowCase Avatar 头像
BadgeViewModel BadgeShowCase Badge 徽标数
CalendarViewModel CalendarShowCase Calendar 日历
CardViewModel CardShowCase Card 卡片
CarouselViewModel CarouselShowCase Carousel 走马灯
CollapseViewModel CollapseShowCase Collapse 折叠面板
DescriptionsViewModel DescriptionsShowCase Descriptions 描述列表
DataGridViewModel DataGridShowCase DataGrid 数据表格
ExpanderViewModel ExpanderShowCase Expander 展开面板
EmptyViewModel EmptyShowCase Empty 空状态
ImagePreviewerViewModel ImagePreviewerShowCase ImagePreviewer 图片预览
GroupBoxViewModel GroupBoxShowCase GroupBox 分组盒
InfoFlyoutViewModel InfoFlyoutShowCase InfoFlyout 信息提示
ListViewModel ListShowCase List 列表
QRCodeViewModel QRCodeShowCase QRCode 二维码
SegmentedViewModel SegmentedShowCase Segmented 分段控制器
StatisticViewModel StatisticShowCase Statistic 统计数值
TagViewModel TagShowCase Tag 标签
TimelineViewModel TimelineShowCase Timeline 时间轴
TreeViewViewModel TreeViewShowCase TreeView 树形控件
TooltipViewModel TooltipShowCase Tooltip 文字提示
TourViewModel TourShowCase Tour 漫游式引导

2.6 Feedback(反馈)— 11 个

ViewModel View 控件
AlertViewModel AlertShowCase Alert 警告提示
DrawerViewModel DrawerShowCase Drawer 抽屉
MessageViewModel MessageShowCase Message 全局提示
ModalViewModel ModalShowCase Modal 对话框
NotificationViewModel NotificationShowCase Notification 通知提醒框
PopupConfirmViewModel PopupConfirmShowCase PopupConfirm 气泡确定框
ProgressBarViewModel ProgressBarShowCase ProgressBar 进度条
ResultViewModel ResultShowCase Result 结果
SkeletonViewModel SkeletonShowCase Skeleton 骨架屏
SpinViewModel SpinShowCase Spin 加载提示
WatermarkViewModel WatermarkShowCase Watermark 水印

3. ViewModel/View 对应关系

3.1 命名约定

层 命名模式 示例
ViewModel {ControlName}ViewModel ButtonViewModel
View (ShowCase) {ControlName}ShowCase ButtonShowCase
View (Page) {ControlName}Page AboutUsPage, OsInfoPage
ViewModel ID EntityKey 静态字段 ButtonViewModel.ID = "Button"

注意:AboutUsPage 和 OsInfoPage 使用 Page 后缀而非 ShowCase,因为它们是信息页面而非控件演示。

3.2 文件组织

ShowCases/
├── ViewModels/
│   └── {Category}/           # 按功能分类
│       └── {ControlName}ViewModel.cs
└── Views/
    └── {Category}/           # 按功能分类(与 ViewModel 对应)
        ├── {ControlName}ShowCase.axaml      # XAML 布局
        └── {ControlName}ShowCase.axaml.cs   # 代码逻辑

4. 路由注册机制

4.1 注册流程

所有 ShowCase ViewModel 在 CaseNavigationViewModel 构造函数中通过 Service Locator 注册:

// CaseNavigationViewModel 构造函数中的注册模式
Locator.CurrentMutable.Register(() => new ButtonViewModel(screen), 
    typeof(IRoutableViewModel), ButtonViewModel.ID.ToString());

每个注册项包含:

  • 工厂 Lambda:() => new XxxViewModel(screen) — 延迟创建 ViewModel
  • 注册类型:typeof(IRoutableViewModel) — 统一注册为可路由 ViewModel
  • 服务 Key:XxxViewModel.ID.ToString() — 用 EntityKey 字符串作为唯一标识

4.2 导航解析

// NavigateTo 方法
public void NavigateTo(string showCaseId)
{
    var viewModel = Locator.Current.GetService<IRoutableViewModel>(showCaseId);
    if (viewModel != null)
    {
        Router.NavigateAndReset.Execute(viewModel);
    }
}

4.3 View 自动解析

ReactiveUI 通过 IViewFor<T> 接口和 RoutedViewHost 自动将 ViewModel 映射到 View:

  • ButtonViewModel → ButtonShowCase(因为 ButtonShowCase : ReactiveUserControl<ButtonViewModel>)
  • WorkspaceWindowViewModel → WorkspaceWindow(因为 WorkspaceWindow : ReactiveWindow<WorkspaceWindowViewModel>)

5. ShowCase View 基类模式

5.1 ReactiveUserControl

所有 ShowCase View 继承自 ReactiveUserControl<XxxViewModel>:

public partial class ButtonShowCase : ReactiveUserControl<ButtonViewModel>
{
    private ButtonViewModel? _viewModel;
    
    public ButtonShowCase()
    {
        this.WhenActivated(disposables =>
        {
            _viewModel = DataContext as ButtonViewModel;
        });
        InitializeComponent();
    }
}

5.2 WhenActivated 生命周期

WhenActivated 是 ReactiveUI 提供的生命周期钩子,在 View 被激活时调用:

  • 用途:获取 ViewModel 引用、设置订阅、执行初始化逻辑
  • 参数:disposables — CompositeDisposable,用于管理订阅生命周期
  • 时机:View 被添加到可视化树后触发
  • 配对:与 IActivatableViewModel 接口配合使用

5.3 事件处理模式

ShowCase View 中的事件处理有两种模式:

模式 1: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;
        });
    }
}

模式 2:ViewModel 属性绑定(部分使用)

// ViewModel 中的响应式属性
private SizeType _buttonSizeType;
public SizeType ButtonSizeType
{
    get => _buttonSizeType;
    set => this.RaiseAndSetIfChanged(ref _buttonSizeType, value);
}

// View 中通过 DataContext 访问
_viewModel.ButtonSizeType = SizeType.Large;

6. ShowCasePanel 布局系统

6.1 布局规则

ShowCasePanel 是 ShowCase 页面的核心布局容器:

  • 2 列 Grid 布局:默认每行放置 2 个 ShowCaseItem
  • 整行占位:ShowCaseItem.IsOccupyEntireRow = true 时独占一行
  • 自动补齐:奇数个 Item 时自动添加一个 IsFake=true 的占位项

6.2 ShowCaseItem 结构

graph TB
    SCI["ShowCaseItem"]
    Title["标题区域<br/>ShowCaseItem.Title"]
    Content["内容区域<br/>[Content] 属性"]
    
    SCI --> Title
    SCI --> Content
  • Title — 展示项标题(如 "基本用法"、"不同尺寸")
  • [Content] — 展示项内容(Avalonia Content 属性)
  • IsOccupyEntireRow — 是否独占整行
  • IsFake — 是否为自动补齐的占位项

6.3 ShowCasePanel 生命周期通知

ShowCasePanel 提供了 4 个生命周期虚方法,供子类覆写:

方法 触发时机
NotifyAboutToActive() 即将激活
NotifyActivated() 已激活
NotifyAboutToDeactivated() 即将停用
NotifyDeactivated() 已停用

7. 新增 ShowCase 步骤

要为一个新的 AtomUI 控件添加 ShowCase,需要以下步骤:

步骤 1:创建 ViewModel

在 ShowCases/ViewModels/{Category}/ 下创建:

using AtomUI;
using ReactiveUI;

namespace AtomUIGallery.ShowCases.ViewModels;

public class NewControlViewModel : ReactiveObject, IRoutableViewModel, IActivatableViewModel
{
    public static EntityKey ID = "NewControl";
    
    public IScreen HostScreen { get; }
    public ViewModelActivator Activator { get; }
    public string UrlPathSegment { get; } = ID.ToString();

    public NewControlViewModel(IScreen screen)
    {
        Activator  = new ViewModelActivator();
        HostScreen = screen;
    }
}

步骤 2:创建 View

在 ShowCases/Views/{Category}/ 下创建:

NewControlShowCase.axaml:

<rxui:ReactiveUserControl xmlns="https://github.com/avaloniaui"
                          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                          xmlns:rxui="clr-namespace:ReactiveUI.Avalonia;assembly=ReactiveUI.Avalonia"
                          xmlns:vm="clr-namespace:AtomUIGallery.ShowCases.ViewModels"
                          x:TypeArguments="vm:NewControlViewModel"
                          x:Class="AtomUIGallery.ShowCases.Views.NewControlShowCase">
    <!-- ShowCase 内容 -->
</rxui:ReactiveUserControl>

NewControlShowCase.axaml.cs:

using AtomUIGallery.ShowCases.ViewModels;
using ReactiveUI;

namespace AtomUIGallery.ShowCases.Views;

public partial class NewControlShowCase : ReactiveUserControl<NewControlViewModel>
{
    public NewControlShowCase()
    {
        this.WhenActivated(disposables => { });
        InitializeComponent();
    }
}

步骤 3:注册路由

在 CaseNavigationViewModel 构造函数中添加注册:

Locator.CurrentMutable.Register(() => new NewControlViewModel(screen), 
    typeof(IRoutableViewModel), NewControlViewModel.ID.ToString());

步骤 4:添加导航项

在 CaseNavigation.axaml 的 NavMenu 中添加导航项。

步骤 5:添加国际化资源

在 Workspace/Localization/CaseNavigationLang/ 的 zh_CN.cs 和 en_US.cs 中添加对应的导航文本。

步骤 6:更新语言资源枚举

Source Generator 会自动扫描 LanguageProvider 子类并生成 CaseNavigationLangResourceKind 枚举,但需要确保新增的 const string 字段名与枚举成员对应。

8. 测试导航功能

Gallery 内置了自动测试导航功能:

  • F5 — 启动自动导航测试,每隔 300ms 自动切换到下一个 ShowCase
  • F6 — 停止自动导航测试

这是通过 CaseNavigation.OnGlobalKeyDown 和 CaseNavigationViewModel.TestNavigatePages/StopTestNavigatePages 实现的。