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

.NET MAUI CommunityToolkit Popups v2弹窗显示期间页面导航引发异常的解决方案咨询

.NET MAUI CommunityToolkit Popups v2弹窗显示期间页面导航引发异常的解决方案咨询

我之前也踩过这个坑!Popups v2改用模态页面作为底层实现后,和Shell导航的栈机制直接产生了冲突——当你调用Shell.Current.GoToAsync跳转到新页面时,新页面会被推到模态栈里,直接把原来的弹窗给阻塞了,这时候再调用CloseAsync就会抛出那个PopupBlockedException。下面是几个亲测有效的解决办法,你可以根据自己的需求选择:

方案一:改用Window级别的弹窗显示(最推荐,改动最小)

原来你是绑定当前页面调用ShowPopupAsync,现在改成绑定主Window来显示弹窗,这样弹窗就不再和单个页面的模态栈绑定,页面导航时就不会被阻塞了。

修改你的ShowPopup方法:

public IPopup ShowPopup<TPopup>() where TPopup : Popup
{
    var popup = serviceProvider.GetRequiredService<TPopup>();
    var popupOptions = CreatePopupOptions(popup);
    // 替换成Window级别的弹窗调用
    var popupTask = Application.Current.MainWindow.ShowPopupAsync(popup, popupOptions);
    return new Types.Popup(popup, popupTask);
}

这个方案完全保留了你原来的弹窗逻辑,只是把弹窗的宿主从页面换成了Window,导航时弹窗会正常保持显示,关闭时也不会再抛出异常。

方案二:捕获异常并清理模态栈(不推荐,仅适用于临时导航场景)

如果因为某些原因必须用页面级弹窗,可以在关闭弹窗时捕获异常,先清理模态栈再关闭。但注意这个操作会把你刚导航过去的页面也弹掉,所以只适合那种临时弹出页面后马上返回的场景:

修改你的Popup wrapper类的CloseAsync方法:

public async Task CloseAsync()
{
    IsClosed = true;
    try
    {
        await popup.CloseAsync();
    }
    catch (PopupBlockedException)
    {
        // 先清空模态栈里的页面
        while (Shell.Current.Navigation.ModalStack.Count > 0)
        {
            await Shell.Current.Navigation.PopModalAsync();
        }
        // 再关闭弹窗
        await popup.CloseAsync();
    }
}

方案三:改用全局加载覆盖层(彻底避开Popup的模态问题)

如果不想再和Popup的模态机制打交道,可以直接做一个全局的加载覆盖层,用ViewModel的属性控制显示/隐藏。比如在App.xaml里定义全局样式:

<Application.Resources>
    <ResourceDictionary>
        <Style TargetType="ContentPage">
            <Setter Property="Overlay">
                <Setter.Value>
                    <Grid IsVisible="{Binding IsLoading}" BackgroundColor="#80000000"
                          HorizontalOptions="Fill" VerticalOptions="Fill">
                        <ActivityIndicator IsRunning="{Binding IsLoading}" 
                                          Color="White" 
                                          HorizontalOptions="Center" 
                                          VerticalOptions="Center"/>
                    </Grid>
                </Setter.Value>
            </Setter>
        </Style>
    </ResourceDictionary>
</Application.Resources>

然后在你的ViewModel里添加IsLoading布尔属性,需要显示加载时设为true,导航完成后设为false。这种方式没有模态栈的限制,完全不会有冲突问题。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 09:03:07