如何在 WPF 中复刻 Visual Studio 2026 的界面、交互和风格¶
- 归档日期:2026-08-26
- 问题:如果想复刻 Visual Studio 2026 的一些界面、交互和风格,应该怎么做?
- 技术口径:Windows 11、Visual Studio 2026、.NET 10 WPF、CommunityToolkit.Mvvm
- 结论性质:专题实施建议,不改变现行技术基线
- 项目主题方向:已选用明净蓝(Luminous Blue)作为轻微主题色调
- 项目主色代码:Coloro
125-28-38/ sRGB#1B3F8D/ WPF ARGB#FF1B3F8D
一句话结论¶
不要把目标定义成“逐像素复制整个 Visual Studio”,而应做成一个“Visual Studio 2026 风格的 WPF Workbench”:以 .NET 10 WPF Fluent Theme 为基础,用自有设计令牌复刻视觉密度和状态,用成熟 Docking 组件复刻文档/工具窗口行为,再用统一命令系统、布局持久化和键盘体系补齐 IDE 级交互。
在当前项目基线下,推荐优先做:
.NET 10 WPF Fluent Theme
+ 自有 VS-inspired Design Tokens
+ Dirkster.AvalonDock v5 两周 POC(开源首选验证项)
+ CommunityToolkit.Mvvm
+ Workbench Shell / Document / ToolPane / Command / Layout 五个服务边界
+ 独立 DesignLab 展示和验证所有组件状态
如果产品是高价值商业软件,且复杂停靠、多显示器、互操作、无障碍和厂商支持很重要,应同时评估 Actipro、DevExpress 或 Syncfusion;不要自己从零实现 Docking 引擎。
一、先明确“复刻”的三个层级¶
层级 1:只复刻视觉语言¶
包括:
- 深浅色和带色调主题。
- 紧凑的信息密度。
- 标签页、工具窗口标题、命令栏、状态栏的形态。
- 字体、图标、细边框、焦点框、悬停和选中状态。
只做这一层,可以使用普通 Grid、TabControl、TreeView 和 DataGrid,成本最低。
层级 2:复刻工作台交互,默认推荐¶
除视觉以外,还包括:
- 多文档标签、未保存状态、固定/预览标签。
- 工具窗口停靠、浮动、自动隐藏、固定和分组。
- 拖动时的 Dock Guide 与落点预览。
Ctrl+Tab文档切换器、快捷键、上下文菜单。- 保存、恢复和重置窗口布局。
- 不同工作模式使用不同布局。
这是大多数“像 Visual Studio 的桌面工具”真正需要达到的层级。
层级 3:复刻完整 IDE¶
还会包含代码编辑器、语法分析、补全、诊断、调试、扩展系统、项目系统等。此时已经不是一个 UI 任务,而是平台产品。除非业务本身就是 IDE,否则不建议把它纳入第一阶段。
二、Visual Studio 2026 最值得借鉴的不是某个颜色¶
微软对 Visual Studio 2026 的公开描述强调了 Fluent UI、排版、图标、布局一致性、降低视觉噪声、无障碍以及 11 个带色调主题;新版设置页还以可搜索、即时生效和透明配置为重点。Visual Studio 官方 UX 介绍
截至 2026-08,VS 2026 已允许用户直接调整活动主题的 Fluent 颜色令牌。这意味着“Visual Studio 2026 的精确颜色”并不是唯一且固定的一组数值;要做高相似度复刻,必须先冻结目标版本、主题和缩放比例。Visual Studio 主题颜色说明
真正应该复刻的是以下系统特征:
- 内容优先:中央文档区占据最多空间,Shell 尽量安静。
- 高密度但不拥挤:大量信息依靠对齐、分组和细微表面差异组织,而不是大卡片和厚重阴影。
- 强状态表达:激活窗口、选中项、键盘焦点、悬停、拖放目标彼此可区分。
- 可重组工作区:用户可以改变布局,并且下次启动仍保留。
- 命令无处不在但来源统一:菜单、工具栏、快捷键、右键菜单和命令搜索只是同一命令模型的不同投影。
- 键盘是一等输入方式:重要流程不能只依赖鼠标拖拽。
三、推荐的 WPF 技术组合¶
| 能力 | 推荐方案 | 说明 |
|---|---|---|
| 基础控件外观 | .NET 10 WPF Fluent Theme | 与现行基线一致,不再叠加 Material/Metro 等完整主题 |
| 视觉系统 | 自有语义 Design Tokens | 控制颜色、密度、字体、边框、图标和动画 |
| MVVM | CommunityToolkit.Mvvm | 文档、工具窗格和命令状态均由 ViewModel 驱动 |
| Docking 开源 POC | Dirkster.AvalonDock v5 | 当前仓库说明支持 net10.0-windows、MVVM Toolkit、DI 和布局序列化 |
| Docking 商业候选 | Actipro / DevExpress / Syncfusion | 适合对多显示器、UIA、互操作、技术支持要求较高的项目 |
| 图标 | 自有 SVG/Geometry 或合规图标集 | 可评估 VS Image Library,但必须遵循随包 EULA |
| 视觉验收 | DesignLab + 截图基线 + 人工评审 | 不以单张主窗口截图作为完成标准 |
Dirkster.AvalonDock v5 的项目说明列出了 .NET 10、MVVM、依赖注入、XML/JSON 布局持久化等能力,适合作为当前技术栈的第一轮开源验证对象。AvalonDock 项目
如果需要商业组件:
- Actipro 明确提供文档/工具窗口、自动隐藏、Dock Guide、
Ctrl+Tab切换器、布局持久化、MVVM 和 UI Automation。Actipro Docking & MDI - DevExpress 提供 Visual Studio 风格停靠、浮动、自动隐藏、分组和布局保存;如果项目已使用 DevExpress 全家桶,集成成本通常更低。DevExpress WPF Docking
- Syncfusion 提供停靠、浮动、自动隐藏、文档分组、Dock Guide、布局恢复和样式定制;如果项目已有对应授权,可纳入 POC。Syncfusion WPF Docking
不要因为某个库内置了旧版 VS 主题就直接使用它。Docking 库负责布局和交互,外观应通过适配层映射到项目自己的语义令牌。
四、先搭 Workbench 骨架¶
推荐的视觉层级:
MainWindow
├─ Title/Command Center 标题、全局搜索、窗口操作
├─ Main Menu / Command Bar 菜单、运行目标、常用命令
├─ Dock Host
│ ├─ Left Tool Panes 导航树、资源浏览器
│ ├─ Document Well 主文档标签和内容
│ ├─ Right Tool Panes 属性、诊断、辅助信息
│ ├─ Bottom Tool Panes 输出、错误、日志、终端
│ └─ Auto-hide Strips 四边自动隐藏入口
└─ Status Bar 状态、进度、环境、告警
首版不要急着自定义标题栏。先保留系统标题栏,完成中央工作区和 Docking;系统标题栏天然保留窗口拖动、最大化、Snap Layout、多显示器 DPI 和无障碍行为。确实需要把搜索框放进标题栏时,再评估 WindowChrome 或按需接入 Windows App SDK。
不建议使用 AllowsTransparency="True" 伪造无边框窗口。它会使渲染、阴影、命中测试、最大化边界和系统窗口行为变得更难维护。
五、建立“VS 风格”设计令牌,不散写颜色和尺寸¶
1. 资源组织¶
Themes/
├─ Base/
│ └─ WpfFluent.xaml
├─ Tokens/
│ ├─ Colors.Semantic.xaml
│ ├─ Density.xaml
│ ├─ Typography.xaml
│ ├─ Geometry.xaml
│ └─ Motion.xaml
├─ Variants/
│ ├─ Light.xaml
│ ├─ Dark.xaml
│ ├─ HighContrast.xaml
│ └─ Tinted.xaml
├─ Controls/
│ ├─ Buttons.xaml
│ ├─ Menus.xaml
│ ├─ Trees.xaml
│ ├─ Tabs.xaml
│ └─ DataGrid.xaml
└─ Workbench/
├─ DocumentTabs.xaml
├─ ToolWindows.xaml
├─ DockGuides.xaml
├─ CommandBar.xaml
└─ StatusBar.xaml
资源覆盖顺序:
在 WPF 中可通过 ThemeMode="System" 加载 Fluent Theme;该 API 当前仍带 WPF0001 实验性标记,而且文档明确建议不要同时再手动加载同一套 Fluent 字典。WPF ThemeMode 文档
2. 语义令牌¶
不要直接定义 VsGray30、VsBlue5,而应按用途定义:
<SolidColorBrush x:Key="Workbench.WindowBackgroundBrush" Color="..." />
<SolidColorBrush x:Key="Workbench.ChromeBackgroundBrush" Color="..." />
<SolidColorBrush x:Key="Workbench.DocumentBackgroundBrush" Color="..." />
<SolidColorBrush x:Key="Workbench.ToolPaneBackgroundBrush" Color="..." />
<SolidColorBrush x:Key="Workbench.BorderSubtleBrush" Color="..." />
<SolidColorBrush x:Key="Workbench.TextPrimaryBrush" Color="..." />
<SolidColorBrush x:Key="Workbench.TextMutedBrush" Color="..." />
<SolidColorBrush x:Key="Workbench.TabActiveBrush" Color="..." />
<SolidColorBrush x:Key="Workbench.TabHoverBrush" Color="..." />
<SolidColorBrush x:Key="Workbench.SelectionBrush" Color="..." />
<SolidColorBrush x:Key="Workbench.FocusBrush" Color="..." />
<SolidColorBrush x:Key="Workbench.DragPreviewBrush" Color="..." />
<SolidColorBrush x:Key="Workbench.StatusInfoBrush" Color="..." />
<SolidColorBrush x:Key="Workbench.StatusWarningBrush" Color="..." />
<SolidColorBrush x:Key="Workbench.StatusErrorBrush" Color="..." />
主题切换时,颜色资源使用 DynamicResource。尺寸、模板和不会变化的几何资源优先使用 StaticResource。
本项目已经确定采用明净蓝(Luminous Blue)作为轻微主题色调。Coloro 参考编号为 125-28-38,项目屏幕主色固定为 sRGB #1B3F8D(RGB 27,63,141),在 WPF 中写作 #FF1B3F8D。该 sRGB 值是项目实现标准;此后不得用其他同名蓝色替换。
实际令牌值固定如下:
| 令牌 | Light | Dark | High Contrast |
|---|---|---|---|
Workbench.AccentBrush |
#FF1B3F8D |
#FF8FAEFF |
{DynamicResource {x:Static SystemColors.HighlightBrushKey}} |
Workbench.AccentHoverBrush |
#FF173575 |
#FFA5BCFF |
系统 Highlight |
Workbench.AccentPressedBrush |
#FF112756 |
#FF7898EC |
系统 Highlight |
Workbench.AccentSubtleBrush |
#261B3F8D |
#408FAEFF |
系统 Highlight |
Workbench.TextOnAccentBrush |
#FFFFFFFF |
#FF000000 |
系统 HighlightText |
明净蓝应通过 Workbench.Accent、Workbench.Focus、Workbench.Selection、Workbench.TabActive 等语义令牌进入界面,主要用于活动边界、标签指示、焦点、选中和主要操作;Light/Dark 中性表面仍然是主体,不应把大面积文档区和非活动工具窗口直接铺成蓝色。High Contrast 不强制保留品牌蓝,应服从用户的系统颜色。
3. 密度令牌¶
以下数值只适合作为 POC 起点,不是微软公布的 VS 2026 精确尺寸:
| 位置 | POC 起点 |
|---|---|
| 菜单/命令栏高度 | 32–36 epx |
| 文档标签高度 | 30–34 epx |
| 工具窗口标题高度 | 28–32 epx |
| 状态栏高度 | 22–24 epx |
| 常用图标 | 16 或 20 epx |
| 紧凑行高 | 24–28 epx |
| 标准输入控件高度 | 30–32 epx |
| 分隔线 | 1 epx |
| 常用间距 | 4 / 8 / 12 / 16 epx |
不要在各个模板里重复这些数字:
<system:Double x:Key="Workbench.CommandBarHeight">34</system:Double>
<system:Double x:Key="Workbench.DocumentTabHeight">32</system:Double>
<system:Double x:Key="Workbench.ToolCaptionHeight">30</system:Double>
<system:Double x:Key="Workbench.StatusBarHeight">22</system:Double>
<system:Double x:Key="Workbench.IconSizeSmall">16</system:Double>
4. 字体与图标¶
- Shell、菜单、树、属性面板使用
Segoe UI Variable,常用字号控制在 12–14 epx。 - 主要正文不应为了“像 IDE”而全部压到 12 epx。
- 代码、日志或等宽数据区单独使用等宽字体,不能让等宽字体扩散到整个 Shell。
- 使用同一套 16/20 epx 矢量图标,统一笔画粗细和视觉边界。
- 仅图标按钮必须有 Tooltip、可访问名称和明显的键盘焦点。
微软提供 Visual Studio 2026 Image Library,并说明其用途是帮助应用在视觉上与 Microsoft 软件保持一致,但下载和使用受随包 EULA 约束。Visual Studio Image Library 对外发布前应逐项确认再分发权利;更稳妥的做法是使用自有图标或许可清晰的 Fluent 风格图标,不直接使用 Visual Studio Logo。
六、交互复刻的优先级高于像素复刻¶
1. 文档标签¶
每个文档至少需要以下状态:
Normal / Hover / Active / KeyboardFocus
Pinned / Preview
Clean / Dirty
Loading / Error
Closable / ClosePending
建议行为:
- 单击激活,鼠标中键关闭可关闭文档。
Ctrl+F4关闭当前文档,Ctrl+Tab打开文档切换器。- 未保存文档显示明确标记;关闭时通过异步关闭协议询问保存,而不是在 View 中直接弹窗。
- 标签过多时提供滚动、溢出列表和搜索,不要无限缩窄标题。
- 文档内容与标签 ViewModel 生命周期分离,关闭后释放订阅和大对象。
2. 工具窗口¶
工具窗口至少支持:
- Dock、Float、AutoHide、Pinned、Hidden。
- 左/右/上/下停靠和同组标签化。
- 拖放目标预览与非法落点反馈。
- 初始位置、最小尺寸、默认尺寸和可用状态限制。
- 关闭后通过“视图”菜单重新打开。
- 浮动窗口跨显示器移动,并在显示器移除后安全回到可见区域。
Visual Studio 本身允许工具窗口和文档窗口停靠、浮动、自动隐藏、分屏,并能命名、保存、应用和重置布局。Visual Studio 窗口布局文档
3. 统一命令系统¶
不要分别在菜单、工具栏和右键菜单里写 Click 事件。一个命令描述应能投影到多个入口:
public sealed record CommandDescriptor(
string Id,
string DisplayName,
string? IconKey,
KeyGesture? DefaultGesture,
ICommand Command,
string Group,
int Order);
推荐边界:
ICommandRegistry
├─ MainMenu
├─ CommandBar
├─ ContextMenu
├─ CommandPalette/Search
└─ KeyboardBinding
必须统一处理 CanExecute、可见性、选中状态、快捷键冲突和命令遥测。这样未来新增“命令搜索”时,不需要重新扫描整个视觉树。
4. 状态与反馈¶
- 激活文档、选中项和键盘焦点必须是三个不同概念。
- 长操作显示可取消进度,不阻塞 UI 线程。
- 状态栏只显示全局、持续或与当前上下文相关的信息。
- 保存成功等短暂反馈可自动消失;错误必须有可继续行动的说明。
- 拖动、展开、自动隐藏弹出使用短而克制的动画,并尊重系统动画偏好。
七、建议的代码边界¶
Product.Client.Presentation/
├─ Workbench/
│ ├─ WorkbenchShellView.xaml
│ ├─ WorkbenchShellViewModel.cs
│ ├─ Documents/
│ │ ├─ DocumentViewModel.cs
│ │ └─ IDocumentService.cs
│ ├─ ToolWindows/
│ │ ├─ ToolWindowViewModel.cs
│ │ └─ IToolWindowService.cs
│ ├─ Commands/
│ │ ├─ CommandDescriptor.cs
│ │ └─ ICommandRegistry.cs
│ ├─ Layout/
│ │ ├─ IWorkbenchLayoutService.cs
│ │ └─ LayoutSnapshot.cs
│ └─ Themes/
│ └─ IThemeService.cs
└─ Features/
└─ ...具体业务页面和面板
基础 ViewModel 可采用:
public abstract partial class WorkbenchItemViewModel : ObservableObject
{
public required string ContentId { get; init; }
[ObservableProperty]
private string title = string.Empty;
[ObservableProperty]
private bool isActive;
[ObservableProperty]
private bool isVisible = true;
}
public abstract partial class DocumentViewModel : WorkbenchItemViewModel
{
[ObservableProperty]
private bool isDirty;
public abstract Task<bool> TryCloseAsync(CancellationToken cancellationToken);
}
public abstract partial class ToolWindowViewModel : WorkbenchItemViewModel
{
public required string DefaultLocation { get; init; }
}
ContentId 必须稳定且与显示标题分离,因为布局文件应保存稳定 ID,不能依赖本地化标题或 View 类型名。
布局持久化规则¶
布局快照建议包含:
SchemaVersion
WorkbenchProfileId
Dock tree / groups / sizes
ContentId and state
Floating window bounds
Active document
Theme/density preference(如果属于用户偏好)
恢复时必须:
- 检查
SchemaVersion并执行迁移。 - 忽略已删除或无权访问的面板。
- 将屏幕外浮动窗口纠正到当前显示器工作区。
- 失败时回退默认布局,而不是让 Shell 无法启动。
- 不在布局文件中保存文档正文、访问令牌或敏感绝对路径。
- 提供“重置布局”和至少一个已知良好布局。
八、推荐实施顺序¶
阶段 0:冻结目标样本,1–2 天¶
记录:
- Visual Studio 2026 的具体版本号。
- 目标主题、是否有自定义主题颜色。
- Windows 缩放比例、分辨率和显示器数量。
- 主窗口、悬停、选中、焦点、菜单、Dock Guide、自动隐藏、浮动窗口等截图。
- 需要复刻和明确不复刻的界面清单。
输出一张组件/状态矩阵,避免开发中不断改变“像 VS”的定义。
阶段 1:静态 Shell 与令牌,3–5 天¶
- 只用假数据搭建标题区、命令栏、中央文档区、左右/底部面板和状态栏。
- 完成 Light、Dark、High Contrast 的资源映射。
- 建立 DesignLab,一次展示组件的全部状态。
- 此阶段不接业务逻辑,不做自定义标题栏。
阶段 2:Docking POC,5–10 天¶
用最复杂场景验证候选库:
- 20 个文档、10 个工具窗口和嵌套分组。
- 停靠、浮动、自动隐藏、固定和跨组拖动。
- 双显示器不同 DPI,断开副屏后恢复。
- 保存/恢复布局以及旧版本布局迁移。
- Light、Dark、High Contrast 下完整换肤。
- 纯键盘操作、Narrator 和 UI Automation。
- 若存在 WinForms、WebView2 或原生 HWND 内容,验证 Airspace 和焦点。
- 重复打开/关闭窗口,检查事件订阅和内存释放。
POC 通过后才锁定组件并写 ADR。若开源库在关键门禁上失败,尽早切换商业库,通常比后期维护自研 Docking 成本更低。
阶段 3:命令、文档和工具窗口模型,5–10 天¶
- 建立统一
ICommandRegistry。 - 打通文档打开、激活、保存、关闭和脏状态。
- 打通工具窗口显示、隐藏、定位和生命周期。
- 实现快捷键、右键菜单、溢出菜单和命令搜索。
阶段 4:视觉精修与真实业务接入,持续进行¶
- 将真实业务页面逐个放入 Workbench,而不是一次迁移全部页面。
- 按截图基线调节令牌,不在页面里做特例补丁。
- 只有确实需要改变视觉树时才重写模板。
- 自定义标题栏、Mica、复杂动画放在最后评估。
九、验收标准¶
视觉¶
- Light、Dark、High Contrast 均无硬编码颜色泄漏。
- 100%、125%、150%、200% DPI 无截断、模糊和一像素错位累积。
- 中文、英文、长标题和超长路径均可处理。
- 文档激活、工具窗格激活、列表选中和键盘焦点可明确区分。
- 截图比较以布局、间距、颜色和状态一致为主,不要求 ClearType 文本逐像素相同。
交互¶
- 只用键盘可打开、切换、关闭文档和工具窗口。
- Dock、Float、AutoHide、Pin、Split 和布局恢复有一致行为。
- 关闭未保存文档时不会丢失数据。
- 异常布局文件不会阻止程序启动。
- 副显示器移除后没有窗口遗留在屏幕外。
性能¶
- 大型树和列表启用 UI Virtualization。
- 工具窗口按需创建,隐藏不等于永久持有全部重资源。
- 启动和布局恢复不在 UI 线程执行磁盘或网络重活。
- 动画不使用大面积实时模糊和多层阴影。
- 文档反复开关后无持续增长的 View、ViewModel 和事件订阅。
无障碍¶
Windows 指南把程序化访问、键盘导航、颜色和对比度列为核心要求;普通文本建议至少 4.5:1,对大文本至少 3:1。Windows 无障碍开发指南 所有自定义标签、Dock Guide 和工具窗口按钮都应提供 Automation Name/Role,并使用 Accessibility Insights、Narrator 和纯键盘流程验证。
十、知识产权边界¶
可以借鉴:
- 工作台信息架构。
- 停靠、浮动、自动隐藏和布局保存等通用交互模式。
- Fluent Design 原则、密度、排版层级和状态表达。
- 在对应许可证允许范围内使用的图标资源。
不应直接复制:
- Visual Studio Logo、产品名称和容易造成官方关系误认的品牌表达。
- 未确认许可证的图标、插图、欢迎页素材和特定品牌资产。
- 用于对外商业产品时,一对一复制全部品牌装潢并暗示它是 Visual Studio。
微软的通用商标指南说明,品牌资产的使用受具体许可和品牌规则约束。Microsoft 商标与品牌指南 如果是公开销售、与 IDE 直接竞争或大量使用微软资产的产品,应在发布前做正式的许可证与商标审查;本节不是法律意见。
十一、我对当前项目的具体建议¶
当前项目已经选择 .NET 10 WPF Fluent Theme + 自有 Design Tokens + CommunityToolkit.Mvvm,因此最稳妥的下一步是:
- 新建
Product.Client.DesignLab中的Workbench页面,先用假数据还原一张目标 VS 2026 工作台。 - 建立上述语义颜色和密度令牌,不复制某个截图中的散装十六进制颜色。
- 用
Dirkster.AvalonDock v5完成两周 POC,并用明确门禁验证多显示器、布局恢复、主题、键盘、UIA 和内存。 - 通过适配层隔离 Docking 库类型,业务 Feature 只依赖
IDocumentService、IToolWindowService和IWorkbenchLayoutService。 - POC 不通过时,在同一测试矩阵下比较 Actipro、DevExpress 和 Syncfusion,不投入自研 Docking。
- 先达到“交互像、层级像、密度像”,最后才做自定义标题栏和细节像素调整。
这条路线能得到一个用户明显感到“像 Visual Studio 2026”的桌面工作台,同时仍保留自己的产品身份、可维护主题和可替换基础组件。
参考资料¶
- A first look at the all-new UX in Visual Studio 2026
- Make Visual Studio look the way you want
- Customize window layouts and personalize tabs
- WPF Window.ThemeMode
- Design Windows apps overview
- Visual Studio Image Library
- Dirkster.AvalonDock
- Actipro Docking & MDI
- DevExpress WPF Docking
- Syncfusion WPF Docking