如何使用ReactiveUI实现类似Visual Studio的启动窗口?
你的ViewModel层级设计是合理的,不需要做大幅度调整,以下是可直接落地的实现方案:
1. 路由与数据留存解决方案
你担心的跳转数据丢失、按钮不固定、手动导航失效的问题都可以通过嵌套路由的方式解决:
- 最外层
StartWindowViewModel作为根路由宿主,持有全局RoutingState,负责切换根级视图:StartViewModel(启动页)和ProjectCreationViewModel(项目创建向导),根视图切换和按钮逻辑完全解耦,不会出现手动导航失效的问题 ProjectCreationViewModel作为向导内部的子路由宿主,自己持有一个独立的RoutingState,负责切换内部的Page1和Page2;同时它直接持有ProjectCreationPage1ViewModel和ProjectCreationPage2ViewModel的单例,跳转时复用同一实例,所有输入数据都会完整保留- 所有页面的底部按钮逻辑都放在对应页面的ViewModel中实现,不需要和路由绑定做全局固定按钮,完全适配你不同页面按钮不同的需求
2. 核心代码实现示例
根路由配置(StartWindowViewModel)
public class StartWindowViewModel : ReactiveObject, IScreen { // 全局根路由状态 public RoutingState Router { get; } = new RoutingState(); public StartWindowViewModel() { // 初始化默认显示启动页 Router.Navigate.Execute(new StartViewModel(this)); } }
启动页跳转逻辑(StartViewModel)
public class StartViewModel : ReactiveObject, IRoutableViewModel { public IScreen HostScreen { get; } public string UrlPathSegment => "StartPage"; // 创建新项目命令,绑定到「创建新项目...」按钮 public ReactiveCommand<Unit, IRoutableViewModel> GoToCreateProject { get; } public StartViewModel(IScreen hostScreen) { HostScreen = hostScreen; GoToCreateProject = ReactiveCommand.CreateFromObservable( () => HostScreen.Router.Navigate.Execute(new ProjectCreationViewModel(HostScreen)) ); } }
项目向导父ViewModel配置
public class ProjectCreationViewModel : ReactiveObject, IScreen, IRoutableViewModel { public IScreen HostScreen { get; } public string UrlPathSegment => "ProjectCreationWizard"; // 向导内部子路由状态 public RoutingState Router { get; } = new RoutingState(); // 常驻两个页面实例,保证数据不丢失 public ProjectCreationPage1ViewModel Page1 { get; } public ProjectCreationPage2ViewModel Page2 { get; } public ProjectCreationViewModel(IScreen rootHost) { HostScreen = rootHost; Page1 = new ProjectCreationPage1ViewModel(this); Page2 = new ProjectCreationPage2ViewModel(this); // 初始化显示第一页 Router.Navigate.Execute(Page1); } }
页面跳转逻辑实现
- Page1的
Cancel命令直接调用根路由的NavigateBack返回启动页 - Page1的
Next命令调用向导子路由的Navigate.Execute(Page2)跳转到第二页 - Page2的
Back命令调用向导子路由的NavigateBack返回第一页,因为Page1实例常驻,所有输入数据都会保留 - Page2的
Finish命令收集Page1和Page2的配置组装成ProjectModel,可以通过消息总线、回调或者根路由的参数传递给启动页,之后调用根路由的NavigateBack返回启动页
3. View层适配
- 最外层
StartWindowView中放置一个RoutedViewHost,绑定到StartWindowViewModel.Router,用于全局根视图切换 ProjectCreationView内部再放置一个RoutedViewHost,绑定到ProjectCreationViewModel.Router,用于向导内部页面切换- 每个页面的底部按钮直接放在对应Page的View中,不需要做全局固定按钮,完全实现类似VS的整页切换效果
内容的提问来源于stack exchange,提问作者Nickelony
相关产品推荐
相关产品推荐

