Avalonia 中实现自定义 路由 和高级导航的核心是将导航行为从 ui 解耦、交由 ViewModel 统一调度,并配合视图自动匹配与过渡动画;使用transitioningContentControl 容器、ViewModel 集中管理导航状态、Ursa.Avalonia 增强菜单导航、或自定义 NavigationService 实现深度定制。

在 Avalonia 中实现自定义 路由 和高级导航,核心不在于“写一 堆跳转代码”,而在于 ** 把导航行为从 UI 解耦、交由 ViewModel 统一调度,并配合视图自动匹配与过渡动画 **。它比传统页面硬跳更灵活,也比手动管理 ContentControl 更健壮。
用 TransitioningContentControl 做容器
这是 Avalonia 推荐的导航基础控件,支持淡入 / 滑动等过渡效果,且天然适配 MVVM 绑定:
- 在主窗口 XAML 中放一个
<transitioningcontentcontrol content="{Binding CurrentPage}"></transitioningcontentcontrol> - 确保项目已启用 ViewLocator(默认模板已配置),这样传入
new ColorsViewModel()时,框架会自动找并加载ColorsView.axaml - 若需自定义切换动画,可设置
Transition属性,例如<slidetransition direction="Right"></slidetransition>
在 ViewModel 里管理导航状态
导航逻辑应集中在主 ViewModel 中,避免代码隐藏文件(.axaml.cs)里写跳转:
- 定义
public Object CurrentPage {get; set;}并用RaiseAndSetIfChanged通知变更 - 用
Stack<object></object>维护历史 栈,实现goBack()时弹出上一页 ViewModel - 导航方法建议带 泛型 约束,如
NavigateTo<t>() where T : new()</t>,保证类型安全且免反射 - 若需参数传递,不要靠 构造函数 硬塞,改用
INavigationService接口 或命令参数(如CommandParameter="{Binding Id}")
用 Ursa.Avalonia 增强多级菜单导航
原生 Avalonia 不内置菜单路由系统,Ursa 提供开箱即用的 NavMenu 组件,适合中后台应用:
- 菜单项绑定
MenuItem集合,每个项可带NavigationCommand,点击即触发跳转 - 支持无限嵌套子菜单(
Children属性)、图标、分隔符、键盘导航(Tab/ 方向键) - 配合
SelectedItem双向绑定,可同步高亮当前页面对应菜单项 - 安装
Irihi.Ursa和主题包后,只需在 XAML 中声明 命名空间xmlns:u="https://irihi.tech/ursa"即可使用
需要深度定制?自己 封装NavigationService
当框架能力不够用(比如要拦截跳转、加权限校验、记录埋点),可手写服务类:
- 注入
IContentControl容器,而非直接持有ContentControl实例,提高测试性 - 在
NavigateTo中插入钩子:检查用户权限、异步加载 页面、显示 loading 遮罩 - 支持 URI 式路由(如
navigate("settings/profile")),配合字典映射到 ViewModel 类型 - 导出为
INavigable接口供各页面 ViewModel 实现,统一生命周期(OnNavigatedTo/OnNavigatedFrom)
基本上就这些。Avalonia 的导航不是黑盒,而是可插拔、可替换的一层抽象——你既可以快速上手 Ursa 的菜单,也能完全掌控每一步跳转细节。关键看项目复杂度和长期维护成本怎么权衡。