UWP开发中如何通过按钮点击实现应用页面跳转
UWP MVVM 架构下按钮点击触发页面导航实现方案
UWP 原生页面导航依赖Frame控件完成,MVVM 模式下不要直接在视图后台写跳转逻辑破坏分层,按以下步骤实现即可:
第一步:抽离导航服务层,解耦ViewModel和视图层逻辑
先定义导航服务的通用接口,方便后续替换实现、做单元测试:public interface INavigationService { // 导航到指定页面 void NavigateTo<TPage>() where TPage : Page; // 后退导航 void GoBack(); // 判断是否可后退 bool CanGoBack { get; } }接着写接口的具体实现,直接复用应用根Frame做导航载体,不需要额外创建控件:
public class NavigationService : INavigationService { private readonly Frame _rootFrame; public NavigationService() { _rootFrame = Window.Current.Content as Frame; if (_rootFrame == null) { _rootFrame = new Frame(); Window.Current.Content = _rootFrame; } _rootFrame.NavigationFailed += (_, e) => throw new InvalidOperationException($"导航到页面 {e.SourcePageType.FullName} 失败", e.Exception); } public bool CanGoBack => _rootFrame.CanGoBack; public void GoBack() { if (CanGoBack) _rootFrame.GoBack(); } public void NavigateTo<TPage>() where TPage : Page { _rootFrame.Navigate(typeof(TPage)); } }第二步:注册导航服务
如果你用官方CommunityToolkit.Mvvm组件配合依赖注入,直接在App.xaml.cs的启动逻辑里注册服务即可:protected override void OnLaunched(LaunchActivatedEventArgs e) { // 你已有的其他初始化逻辑 Frame rootFrame = Window.Current.Content as Frame; if (rootFrame == null) { rootFrame = new Frame(); Window.Current.Content = rootFrame; } var navigationService = new NavigationService(); // 注册到IOC容器 Ioc.Default.ConfigureServices( new ServiceCollection() .AddSingleton<INavigationService>(navigationService) .AddTransient<MainViewModel>() // 你已有的ViewModel .AddTransient<NewPageViewModel>() // 新页面对应的ViewModel .BuildServiceProvider() ); // 应用启动时默认导航到主页面 if (rootFrame.Content == null) { navigationService.NavigateTo<MainPage>(); } Window.Current.Activate(); }如果你没接入依赖注入,直接把导航服务做成全局单例也能正常用,只是可测试性稍差,个人项目完全可以接受。
第三步:在对应ViewModel中添加导航命令
用MVVM工具包自带的RelayCommand特性生成命令,不需要自己手动实现ICommand接口:public partial class MainViewModel : ObservableObject { private readonly INavigationService _navigationService; // 构造函数自动注入导航服务 public MainViewModel(INavigationService navigationService) { _navigationService = navigationService; } [RelayCommand] private void JumpToNewPage() { // 这里可以加跳转前的初始化逻辑:比如参数赋值、数据预加载、权限校验都可以写在这 _navigationService.NavigateTo<NewPage>(); } }第四步:视图层绑定命令
不需要给按钮加Click后台事件,直接在XAML里把按钮的Command属性绑定到ViewModel里生成的命令即可:<Button Content="打开新页面" Command="{Binding JumpToNewPageCommand}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
补充说明:如果需要给新页面传递参数,直接给
Navigate方法加object类型的参数重载即可,目标页面重写OnNavigatedTo方法就能接收传值;不要在ViewModel里直接操作Frame实例,否则会导致视图层和逻辑层强耦合,后续改页面结构、写单元测试都会很麻烦。
内容的提问来源于stack exchange,提问作者Szymon Kucharski
相关产品推荐
相关产品推荐

