You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在无Shell的MAUI应用中从ViewModel实现导航?

在MAUI无Shell架构下从ViewModel实现页面导航的方法

以下是几种实用的实现方案,适配MVVM架构的解耦需求:

1. 实现独立导航服务(推荐,低耦合)

通过定义导航服务接口并实现,将导航逻辑从页面和ViewModel中剥离:

步骤1:定义导航服务接口

public interface INavigationService
{
    Task PushAsync(Page page);
    Task PopAsync();
    Task PushModalAsync(Page page);
    Task PopModalAsync();
    // 可根据需求扩展其他导航方法
}

步骤2:实现导航服务

public class NavigationService : INavigationService
{
    private readonly INavigation _navigation;

    public NavigationService(INavigation navigation)
    {
        _navigation = navigation;
    }

    public Task PushAsync(Page page) => _navigation.PushAsync(page);
    public Task PopAsync() => _navigation.PopAsync();
    public Task PushModalAsync(Page page) => _navigation.PushModalAsync(page);
    public Task PopModalAsync() => _navigation.PopModalAsync();
}

步骤3:注册并初始化服务

在App.xaml.cs中注册服务,传入主页面的Navigation实例:

public App()
{
    InitializeComponent();
    var mainPage = new MainPage();
    DependencyService.RegisterSingleton<INavigationService>(new NavigationService(mainPage.Navigation));
    MainPage = mainPage;
}

步骤4:在ViewModel中注入使用

public class MyViewModel
{
    private readonly INavigationService _navService;
    public ICommand NavigateCommand { get; }

    public MyViewModel(INavigationService navService)
    {
        _navService = navService;
        NavigateCommand = new Command(async () => await NavigateToNewPage());
    }

    private async Task NavigateToNewPage()
    {
        await _navService.PushAsync(new NewPage1());
    }
}

2. 直接传递Navigation对象到ViewModel(适合小型项目)

在页面构造时,将自身的Navigation实例传递给ViewModel:

页面代码

public MainPage()
{
    InitializeComponent();
    BindingContext = new MyViewModel(Navigation);
}

ViewModel代码

public class MyViewModel
{
    private readonly INavigation _navigation;
    public ICommand NavigateCommand { get; }

    public MyViewModel(INavigation navigation)
    {
        _navigation = navigation;
        NavigateCommand = new Command(async () => await _navigation.PushAsync(new NewPage1()));
    }
}

这种方式简单直接,但ViewModel与页面存在轻微耦合,适合小型应用快速开发。

3. 使用WeakReferenceMessenger发送导航消息(完全解耦)

通过消息机制实现ViewModel与页面的解耦,ViewModel发送导航请求,页面订阅并执行导航:

定义导航消息类

public class NavigateToPageMessage
{
    public Type TargetPageType { get; }

    public NavigateToPageMessage(Type pageType)
    {
        TargetPageType = pageType;
    }
}

ViewModel中发送消息

public class MyViewModel
{
    public ICommand NavigateCommand { get; }

    public MyViewModel()
    {
        NavigateCommand = new Command(() => 
        {
            WeakReferenceMessenger.Default.Send(new NavigateToPageMessage(typeof(NewPage1)));
        });
    }
}

页面中订阅消息

public MainPage()
{
    InitializeComponent();
    BindingContext = new MyViewModel();
    
    WeakReferenceMessenger.Default.Register<NavigateToPageMessage>(this, (_, msg) =>
    {
        var targetPage = (Page)Activator.CreateInstance(msg.TargetPageType);
        Navigation.PushAsync(targetPage);
    });
}

推荐使用WeakReferenceMessenger(MAUI官方推荐),避免旧版MessagingCenter的内存泄漏问题。

内容的提问来源于stack exchange,提问作者Tiago Rosolen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 07:04:54