.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
相关产品推荐
相关产品推荐

