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

MAUI开发:如何在ViewModel中使用PopupService显示弹窗?

解决ViewModel中使用PopupService显示弹窗的KeyNotFoundException问题

你遇到的KeyNotFoundException是因为自定义PopupService的ShowPopup方法未实现正确的弹窗显示逻辑,而Shell.Current.ShowPopup是MAUI框架提供的标准实现,能正确处理弹窗的上下文注册。

要在ViewModel中解耦Shell依赖,同时正常显示弹窗,可按以下步骤修改:

1. 定义IPopupService接口

先抽象弹窗服务的接口,让ViewModel仅依赖抽象而非具体实现:

public interface IPopupService
{
    Popup GetPopup(object sender);
    void ShowPopup(Popup popup);
}

2. 完善PopupService实现

在实现类中封装框架的弹窗显示逻辑,避免ViewModel直接依赖Shell:

public class PopupService : IPopupService
{
    public Popup GetPopup(object sender)
    {
        var button = sender as ImageButton;
        var popup = new CustomPopup
        {
            Anchor = button
        };

        return popup;
    }

    public void ShowPopup(Popup popup)
    {
        // 内部调用框架弹窗方法,ViewModel无需感知Shell
        Shell.Current.ShowPopup(popup);
    }
}

若不想依赖Shell,也可通过DI获取当前Window实现显示:

private readonly IServiceProvider _serviceProvider;

public PopupService(IServiceProvider serviceProvider)
{
    _serviceProvider = serviceProvider;
}

public void ShowPopup(Popup popup)
{
    var currentWindow = _serviceProvider.GetRequiredService<Microsoft.Maui.Controls.Window>();
    currentWindow.ShowPopup(popup);
}

3. 注册服务到DI容器

在MauiProgram.cs中添加服务注册:

builder.Services.AddSingleton<IPopupService, PopupService>();

4. ViewModel中注入并使用

通过构造函数注入IPopupService,替换原直接实例化的方式:

private readonly IPopupService _popupService;

// 构造函数注入服务
public YourViewModel(IPopupService popupService)
{
    _popupService = popupService;
}

[RelayCommand]
private async Task ShowPopupAsync(object sender)
{
     var popup = _popupService.GetPopup(sender);
     _popupService.ShowPopup(popup);
}

修改后既保持了ViewModel与UI层的解耦,又能正确调用框架弹窗逻辑,不会再出现KeyNotFoundException。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 18:42:47