diff --git a/src/Maui/Prism.Maui/Dialogs/DialogContainerPage.cs b/src/Maui/Prism.Maui/Dialogs/DialogContainerPage.cs index 42f40ab98..ad3cd0de2 100644 --- a/src/Maui/Prism.Maui/Dialogs/DialogContainerPage.cs +++ b/src/Maui/Prism.Maui/Dialogs/DialogContainerPage.cs @@ -89,7 +89,12 @@ public virtual async Task DoPop(Page currentPage) /// The content layout for the dialog container page. protected virtual View GetContentLayout(Page currentPage, View dialogView, bool hideOnBackgroundTapped, ICommand dismissCommand, IDialogParameters parameters) { - var overlay = new AbsoluteLayout(); + // Use a Grid so the mask fills the page naturally without needing + // AbsoluteLayout proportional sizing, which conflicted with the + // WidthRequest/HeightRequest bindings and caused tap gestures on + // the mask to not fire reliably across MAUI platforms. + var overlay = new Grid(); + var popupContainer = new DialogContainerView { IsPopupContent = true, @@ -118,20 +123,21 @@ protected virtual View GetContentLayout(Page currentPage, View dialogView, bool source: this)); } - AbsoluteLayout.SetLayoutFlags(popupContainer, AbsoluteLayoutFlags.PositionProportional); - var popupBounds = DialogLayout.GetLayoutBounds(dialogView); - AbsoluteLayout.SetLayoutBounds(popupContainer, popupBounds); - - var useMask = DialogLayout.GetUseMask(popupContainer.Content) ?? true; + var useMask = DialogLayout.GetUseMask(dialogView) ?? true; if (useMask) { var mask = GetMask(currentPage, dialogView, hideOnBackgroundTapped, dismissCommand); - AbsoluteLayout.SetLayoutFlags(mask, AbsoluteLayoutFlags.All); - AbsoluteLayout.SetLayoutBounds(mask, new Rect(0, 0, 1, 1)); overlay.Children.Add(mask); } - overlay.Children.Add(popupContainer); + // Keep an AbsoluteLayout for the popup so LayoutBounds positioning still works + var popupArea = new AbsoluteLayout(); + AbsoluteLayout.SetLayoutFlags(popupContainer, AbsoluteLayoutFlags.PositionProportional); + var popupBounds = DialogLayout.GetLayoutBounds(dialogView); + AbsoluteLayout.SetLayoutBounds(popupContainer, popupBounds); + popupArea.Children.Add(popupContainer); + + overlay.Children.Add(popupArea); return overlay; } @@ -146,7 +152,6 @@ protected virtual View GetContentLayout(Page currentPage, View dialogView, bool private View GetMask(Page currentPage, View dialogView, bool hideOnBackgroundTapped, ICommand dismissCommand) { View mask = DialogLayout.GetMask(dialogView); - var reference = currentPage.GetParentWindow().Page; if (mask is null) { Style overlayStyle = GetOverlayStyle(dialogView, currentPage); @@ -154,21 +159,11 @@ private View GetMask(Page currentPage, View dialogView, bool hideOnBackgroundTap mask = new BoxView { Style = overlayStyle, - //HeightRequest = reference.Height, - //WidthRequest = reference.Width }; } - mask.SetBinding(WidthRequestProperty, new Binding - { - Path = nameof(Width), - Source = reference - }); - mask.SetBinding(HeightRequestProperty, new Binding - { - Path = nameof(Height), - Source = reference - }); + // No explicit WidthRequest/HeightRequest needed — the Grid parent + // sizes the mask to fill the page automatically. if (hideOnBackgroundTapped) { diff --git a/src/Maui/Prism.Maui/Dialogs/DialogService.cs b/src/Maui/Prism.Maui/Dialogs/DialogService.cs index d36a6d0f4..6d97bd48b 100644 --- a/src/Maui/Prism.Maui/Dialogs/DialogService.cs +++ b/src/Maui/Prism.Maui/Dialogs/DialogService.cs @@ -1,4 +1,5 @@ using Prism.Common; +using Prism.Navigation; #nullable enable namespace Prism.Dialogs; @@ -9,18 +10,36 @@ namespace Prism.Dialogs; public sealed class DialogService : DialogServiceBase { private readonly IPageAccessor _pageAccessor; + private readonly IWindowManager _windowManager; /// /// Creates a new instance of the for Maui Applications /// /// The used to determine where in the Navigation Stack we need to process the Dialog. + /// The used to resolve the current page when the scoped page is no longer attached. /// Throws when any constructor arguments are null. - public DialogService(IPageAccessor pageAccessor) + public DialogService(IPageAccessor pageAccessor, IWindowManager windowManager) { ArgumentNullException.ThrowIfNull(pageAccessor); + ArgumentNullException.ThrowIfNull(windowManager); _pageAccessor = pageAccessor; + _windowManager = windowManager; } /// - protected override Page? GetCurrentPage() => _pageAccessor.Page; + protected override Page? GetCurrentPage() + { + var page = _pageAccessor.Page; + + // If the scoped page is still connected to a window, use it + if (page?.GetParentWindow() is not null) + return page; + + // Fallback: the scoped page was detached (e.g. after absolute navigation). + // Resolve the current page from the active window instead. + if (_windowManager.Current is PrismWindow prismWindow) + return prismWindow.CurrentPage; + + return page; + } } diff --git a/src/Maui/Prism.Maui/Dialogs/DialogServiceBase.cs b/src/Maui/Prism.Maui/Dialogs/DialogServiceBase.cs index 940520836..dbe81e8a8 100644 --- a/src/Maui/Prism.Maui/Dialogs/DialogServiceBase.cs +++ b/src/Maui/Prism.Maui/Dialogs/DialogServiceBase.cs @@ -97,12 +97,23 @@ async Task DialogAware_RequestClose(IDialogResult outResult) var dismissCommand = new DelegateCommand(() => dialogAware.RequestClose.Invoke(), dialogAware.CanCloseDialog); + // ConfigureLayout is async (it awaits DoPush internally). Since ShowDialog is void, + // we use ContinueWith to defer post-push work until the modal is actually displayed. + // Without this, NavigationSource resets and IsActive updates race ahead of the push. PageNavigationService.NavigationSource = PageNavigationSource.DialogService; - dialogModal.ConfigureLayout(currentPage, view, closeOnBackgroundTapped, dismissCommand, parameters); - PageNavigationService.NavigationSource = PageNavigationSource.Device; + dialogModal.ConfigureLayout(currentPage, view, closeOnBackgroundTapped, dismissCommand, parameters) + .ContinueWith(t => + { + if (t.IsFaulted) + { + callback.Invoke(t.Exception?.InnerException ?? t.Exception); + return; + } - MvvmHelpers.InvokeViewAndViewModelAction(currentPage, aa => aa.IsActive = false); - MvvmHelpers.InvokeViewAndViewModelAction(view, aa => aa.IsActive = true); + PageNavigationService.NavigationSource = PageNavigationSource.Device; + MvvmHelpers.InvokeViewAndViewModelAction(currentPage, aa => aa.IsActive = false); + MvvmHelpers.InvokeViewAndViewModelAction(view, aa => aa.IsActive = true); + }, TaskScheduler.FromCurrentSynchronizationContext()); } catch (Exception ex) { diff --git a/src/Maui/Prism.Maui/Navigation/PrismWindow.cs b/src/Maui/Prism.Maui/Navigation/PrismWindow.cs index bd0debf92..2ad4dcf2b 100644 --- a/src/Maui/Prism.Maui/Navigation/PrismWindow.cs +++ b/src/Maui/Prism.Maui/Navigation/PrismWindow.cs @@ -105,7 +105,7 @@ protected override void OnActivated() protected override void OnDeactivated() { IsActive = false; - MvvmHelpers.InvokeViewAndViewModelAction(CurrentPage, x => x.IsActive = true); + MvvmHelpers.InvokeViewAndViewModelAction(CurrentPage, x => x.IsActive = false); } ///