Reactor¶
Microsoft.UI.Reactor(以下简称 Reactor)是一个声明式 UI 框架,用于以纯 C# 构建原生 Windows 桌面应用。没有 XAML,没有数据绑定,没有视图模型。你把 UI 描述成状态的函数,Reactor 负责让屏幕与状态保持同步。
| 如果你想…… | 从这里开始 |
|---|---|
| 构建第一个 Reactor 应用 | 快速上手 |
| 理解思维模型 | Reactor 思维模型 |
| 移植 XAML/WinUI/WPF 应用 | 面向 XAML 开发者的 Reactor |
| 查阅某个 Hook 或修饰符 | API 参考 |
| 了解运行时的工作原理 | 架构概览 |
为什么选择 Reactor?¶
自上而下纯 C#。 你的整个应用——布局、样式、状态、逻辑——都写在 .cs 文件里。没有标记语言,没有 code-behind 的分离,也没有设计器生成文件。
声明式渲染。 你编写一个返回 UI 的 Render() 方法。当状态发生变化时,Reactor 对新旧元素树做差异比对,只把变化的部分打补丁到原生 WinUI 控件上。
用 Hook 管理状态。 UseState、UseReducer、UseEffect 等一系列 Hook 为你带来 React 风格的状态管理,却不需要写一行 JavaScript。
原生性能。 Reactor 渲染出的是真正的 WinUI 3 控件。你的应用就是一个标准的 Windows 桌面应用——不内嵌 WebView,不用 Electron,没有解释层。
快速一览¶
一个完整的 Reactor 应用,全部写在一个文件里:
class HelloWorld : Component
{
public override Element Render()
{
return VStack(12,
TextBlock("Hello from Reactor!").FontSize(24).Bold(),
TextBlock("No XAML. No data binding. Just C#.")
).Padding(24);
}
}

几行代码搞定状态与交互:
class QuickCounter : Component
{
public override Element Render()
{
var (count, setCount) = UseState(0);
return HStack(8,
Button("- 1", () => setCount(count - 1)),
TextBlock($"{count}").FontSize(20).SemiBold().Width(40)
.HAlign(HorizontalAlignment.Center),
Button("+ 1", () => setCount(count + 1))
).Padding(24);
}
}

内置的文本样式:
class StyledText : Component
{
public override Element Render()
{
return VStack(8,
Heading("Heading element"),
SubHeading("SubHeading element"),
TextBlock("Regular text with modifiers")
.FontSize(14).Foreground(Theme.Accent),
Caption("Caption for fine print")
).Padding(24);
}
}

工作原理¶
- 定义组件——带有
Render()方法、返回元素树的类。 - 用 Hook 管理状态——
UseState、UseReducer、UseEffect等等,都在Render()内部调用。 - 状态变化时,Reactor 重新调用
Render(),对结果做差异比对,只更新那些真正发生变化的 WinUI 控件。
就是这么简单。没有需要自己管理的事件订阅,没有需要接线的属性变更通知,也没有需要操心的调度线程问题。
文档¶
本套文档分为十节,从"让第一个应用出现在屏幕上"一路讲到"运行时是怎么造出来的"。XAML 开发者建议先读第 1、8、9 节,其他读者按章节顺序阅读即可。
1. 快速上手¶
- 快速上手 — 创建第一个应用、管理状态、完成一个待办清单
- Reactor 思维模型 — 思维模型长文:UI 是状态的函数
- 面向 XAML 开发者的 Reactor — 迁移手册:XAML、绑定、MVVM、导航
- Reactor 与 XAML 的对比 — 架构长文:依赖属性 → 修饰符,绑定 → 闭包
2. 学习框架¶
- 组件 — 组件类、props、函数组件、组合
- Hook — UseState、UseReducer、UseEffect、UseMemo、UseRef、UseCallback
- 副作用与生命周期 — UseEffect 的各类用法、清理、异步工作、定时器
- 上下文(Context) — 在组件树中共享状态,无需逐层传递 props
- 命令(Commanding) — 命令、键盘快捷键、异步操作
- 高级模式 — ErrorBoundary、Memo、可观察对象绑定、性能调优
3. UI 呈现¶
- 布局 — VStack、HStack、Grid、ScrollView、Border,以及响应式模式
- 弹性布局(Flex Layout) — 面向自适应 UI 的 flex 盒式布局
- 样式与主题 — 颜色、字体排版、深色/浅色主题、自定义样式
- 动画 — 过渡、关键帧、交互状态、动画编排
- 输入与手势 — 指针事件、点击、手势、访问键
4. 控件目录¶
- 控件 — 带缩略图索引的全量控件目录
- 表单与输入 — 文本框、复选框、滑块、校验、数据录入
- 集合 — 面向大数据集的 ListView、LazyVStack、VirtualList
- 文本与媒体 — TextBlock、MarkdownTextBlock、Image、MediaPlayerElement、WebView2、InkCanvas
- 状态与信息 — InfoBar、InfoBadge、ProgressBar、TeachingTip、PipsPager
- 对话框与浮出层 — ContentDialog、MenuFlyout、CommandBarFlyout、Popup
- 数据系统 — 支持排序、筛选、搜索与行内编辑的 DataGrid
- 图表 — 使用 ReactorCharting 库绘制折线图、柱状图、面积图、饼图
- Win2D 画布 — 来自可选包
Microsoft.UI.Reactor.Advanced的即时模式绘图表面(手动、动画、虚拟三种)
5. 应用架构¶
- 导航 — NavigationView、TabView、多页面应用、路由
- 窗口 — 顶层窗口、托盘图标、跳转列表、
OpenWindow、关闭策略 - 高级窗口特性 — 分层叠加层、窗口区域,以及其他重度依赖互操作的范例
- 停靠窗口 — 可重排的停靠面板:拆分、标签页、侧边固定、浮动拖出、布局持久化
- 异步资源 —
UseResource、UseInfiniteResource、UseMutation、Pending - 持久化 — UsePersisted、作用域、迁移
- 本地化 — 多语言支持、资源字符串、RTL(从右向左)布局
- 无障碍 — 屏幕阅读器、键盘导航、焦点捕获、运行时扫描
6. 模式与实践范例¶
- 实践范例 — 端到端模式合集(登录、主从视图、分页列表、命令面板……)
- 速查表 — 单页速查卡片
- Reactor 准则 — Hook 规则、渲染纯度、反面模式
- 主题令牌 — 附色板的完整令牌目录
7. 工具与流程¶
- 开发工具 —
murCLI、MCP 服务器、VS Code 面板、dotnet watch、应用内开发菜单 - Visual Studio 扩展 — 面向 Visual Studio 2022 (17.8+) 与 2026 (18.x) 的粗略实验性内嵌预览
- 测试 — 无头渲染器、结构断言、异步测试模式
- 性能 — ETW、EventDispatch、火焰图
- 打包 — MSIX、单文件、ARM64、AOT 相关考量
8. 互操作与集成¶
- WinForms 互操作 — 通过 XAML Islands 在 WinForms 应用中承载 Reactor 组件
- WPF 互操作 — 在 WPF 应用中承载 Reactor 组件
(XAML 迁移内容放在第 1 节——XAML 开发者是主要入口路径之一。)
9. 底层原理¶
运行时解析——写给那些不满足于"怎么用"、还想知道它为什么是这样设计的读者。
- 架构概览 — 声明式外壳 → 元素记录 → 协调器 → WinUI 树
- 响应式模型 — setState → 重新渲染;为什么用 Hook 而不是 INotifyPropertyChanged
- Reactor 与 XAML 的对比 — 架构长文(同时收录于第 1 节)
- Hook 内部机制 — Hook 槽位表、调度器、闭包捕获
- 协调(Reconciliation) — 元素记录 diff、身份标识、三个阶段
- 控件协调器协议 — 按控件划分的处理器协议:
IElementHandler、描述符、子节点策略、池化 - 扩展 Reactor 控件 — 实操手册:用描述符端到端接入一个原生控件
- 元素池 — 在重度滚动列表中减少内存分配
- 副作用调度 — 副作用何时执行;依赖语义;清理顺序
- 线程与调度 — UI 线程不变式、蹦床(trampoline)机制、批量渲染
- 源码映射 — 堆栈跟踪与开发工具如何回溯到用户源码
- 修饰符系统 —
.FontSize(24).Bold()到底是怎么工作的 - 分析器架构 — Reactor 随包发布的 Roslyn 分析器;以及如何编写自己的分析器
- DevTools 内部机制 — 开发菜单、协调高亮覆盖层、MCP 协议
- 动画管线 — 端到端打通 Composition API;4 套动画系统
- 焦点与输入内部机制 —
UseFocus调度器、FocusTrap容器、指针事件流 - 性能埋点 — ETW 事件源、按帧对齐的采样
10. API 参考¶
由 src/Reactor*/ 中的 XML 文档注释自动生成。每个成员都有一套统一的页面结构:摘要 / 参数 / 返回值 / 说明 / 示例 / 另请参阅。
- Hook — 每一个
Use*Hook - 工厂(Factories) — 每一个元素工厂(即将推出)
- 修饰符(Modifiers) — 每一个可链式调用的修饰符(即将推出)
- 元素(Elements) — 每一种元素记录类型(即将推出)
- 系统(System) — App、Window、Navigation、Context、Command(即将推出)
最小项目配置¶
最快的路径是 dotnet new reactorapp,它会替你搭好下面这一切。若想手动配置,则创建一个控制台项目并编辑 .csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net10.0-windows10.0.22621.0</TargetFramework>
<UseWinUI>true</UseWinUI>
<WindowsPackageType>None</WindowsPackageType>
<!-- Windows App SDK needs a concrete architecture; without this an
unqualified `dotnet build` / `dotnet run` fails with
"WindowsAppSDKSelfContained requires a supported Windows architecture". -->
<RuntimeIdentifier Condition="'$(RuntimeIdentifier)' == '' And ('$(Platform)' == '' Or '$(Platform)' == 'AnyCPU')">$(NETCoreSdkPortableRuntimeIdentifier)</RuntimeIdentifier>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.UI.Reactor" Version="0.1.0-preview.15" />
</ItemGroup>
</Project>
只需一个包引用就够了——Microsoft.UI.Reactor 会以传递依赖的方式引入 Windows 应用 SDK,所以只有在你想锁定某个特定的 WinUI 补丁版本,或想通过 WindowsAppSDKSelfContained 把运行时一起打包时,才需要自己添加 Microsoft.WindowsAppSDK。项目模板使用的 <Platforms>、ARM64 与自包含形态,参见打包。
把 App.cs 换成一个组件加一次 ReactorApp.Run<T>() 调用,然后 dotnet run——你的第一个 Reactor 应用就跑起来了。
小贴士¶
从函数组件开始。 如果只是想快速试验,可以用 ReactorApp.Run("Title", ctx => { ... })——连类都不用定义。
读一读 Hook 那一页。 Hook 是 Reactor 的核心。理解了 UseState 和 UseEffect,其余一切都迎刃而解。
保持组件短小。 尽早把局部内容抽成独立组件。由组合构成的结构,永远比一个巨大的 Render() 更容易推理。
下一步¶
- 快速上手 — 构建第一个应用、管理状态、完成一个待办清单。
- Hook —
UseState、UseEffect、UseMemo,以及其他核心状态原语。 - 组件 — 组件类、props 与函数组件详解。
- 面向 XAML 开发者的 Reactor — XAML、绑定、MVVM 与导航的迁移手册。