From 87a65f30218a8e247c1093879ec3da008f93ff7f Mon Sep 17 00:00:00 2001 From: Dan Siegel Date: Wed, 28 Feb 2024 12:49:19 -0600 Subject: [PATCH] feat: support getting the current IDialogService from a Singleton --- src/Maui/Prism.Maui/Common/MvvmHelpers.cs | 38 ++++++++++++++----- .../Prism.Maui/Navigation/IWindowManager.cs | 25 +++++++++++- .../Navigation/IWindowManagerExtensions.cs | 34 ++++++++++++++--- src/Maui/Prism.Maui/Navigation/PrismWindow.cs | 2 +- .../Navigation/PrismWindowManager.cs | 13 ++++++- 5 files changed, 94 insertions(+), 18 deletions(-) diff --git a/src/Maui/Prism.Maui/Common/MvvmHelpers.cs b/src/Maui/Prism.Maui/Common/MvvmHelpers.cs index f75b3dba85..b113162cf0 100644 --- a/src/Maui/Prism.Maui/Common/MvvmHelpers.cs +++ b/src/Maui/Prism.Maui/Common/MvvmHelpers.cs @@ -1,5 +1,6 @@ -using System.ComponentModel; +using System.ComponentModel; using System.Reflection; +using Prism.Dialogs; using Prism.Navigation; using Prism.Navigation.Regions; using Prism.Navigation.Xaml; @@ -272,27 +273,44 @@ public static void SetCurrentPageDelegate(Func getCurrentPageDelegat return EvaluateCurrentPage(page); }; - private static Page EvaluateCurrentPage(Page target) + private static Page GetTarget(Page target) { - Page child = null; + return target switch + { + FlyoutPage flyout => GetTarget(flyout.Detail), + TabbedPage tabbed => GetTarget(tabbed.CurrentPage), + NavigationPage navigation => GetTarget(navigation.CurrentPage), + ContentPage page => page, + _ => throw new NotSupportedException($"The page type '{target.GetType().FullName}' is not supported.") + }; + } - if (target is FlyoutPage flyout) - child = flyout.Detail; - else if (target is TabbedPage tabbed) - child = tabbed.CurrentPage; - else if (target is NavigationPage np) - child = np.Navigation.NavigationStack.Last(); + private static Page EvaluateCurrentPage(Page target) + { + Page child = GetTarget(target); - if (child != null) + if (child is not null) target = GetOnNavigatedToTargetFromChild(child); if (target is Page page) + { + if (target is IDialogContainer) + { + if (page.Parent is Page parentPage) + { + return GetTarget(parentPage); + } + + throw new InvalidOperationException("Unable to determine the current page."); + } + return page.Parent switch { TabbedPage tab when tab.CurrentPage != target => EvaluateCurrentPage(tab.CurrentPage), NavigationPage nav when nav.CurrentPage != target => EvaluateCurrentPage(nav.CurrentPage), _ => target }; + } return null; } diff --git a/src/Maui/Prism.Maui/Navigation/IWindowManager.cs b/src/Maui/Prism.Maui/Navigation/IWindowManager.cs index b51b715598..1be6cf3543 100644 --- a/src/Maui/Prism.Maui/Navigation/IWindowManager.cs +++ b/src/Maui/Prism.Maui/Navigation/IWindowManager.cs @@ -1,10 +1,33 @@ -using System; namespace Prism.Navigation; +#nullable enable +/// +/// Defines an interface for managing windows within an application. +/// public interface IWindowManager { + /// + /// Gets a read-only collection of all currently open windows. + /// IReadOnlyList Windows { get; } + /// + /// Gets the currently active window, if any. + /// + Window? Current { get; } + + /// + /// Opens a new window. + /// + /// The Window object to be opened. + /// Thrown if the window parameter is null. void OpenWindow(Window window); + + /// + /// Closes a specified window. + /// + /// The Window object to be closed. + /// Thrown if the window parameter is null. void CloseWindow(Window window); } + diff --git a/src/Maui/Prism.Maui/Navigation/IWindowManagerExtensions.cs b/src/Maui/Prism.Maui/Navigation/IWindowManagerExtensions.cs index 237f1e14c0..0c972a26e4 100644 --- a/src/Maui/Prism.Maui/Navigation/IWindowManagerExtensions.cs +++ b/src/Maui/Prism.Maui/Navigation/IWindowManagerExtensions.cs @@ -1,4 +1,7 @@ -namespace Prism.Navigation; +using Prism.Dialogs; +using Prism.Navigation.Xaml; + +namespace Prism.Navigation; /// /// Provides extensions for the @@ -12,11 +15,32 @@ public static class IWindowManagerExtensions /// The for the current . public static INavigationService GetCurrentNavigationService(this IWindowManager windowManager) { - var window = windowManager.Windows.OfType().First(); + var page = windowManager.GetCurrentPage(); + return Xaml.Navigation.GetNavigationService(page); + } - if (window.CurrentPage is null) - throw new InvalidOperationException("No current page has been set."); + /// + /// Gets the for the currently displayed . + /// + /// The . + /// The for the current . + public static IDialogService GetCurrentDialogService(this IWindowManager windowManager) + { + var page = windowManager.GetCurrentPage(); + var container = page.GetContainerProvider(); + return container.Resolve(); + } - return Xaml.Navigation.GetNavigationService(window.CurrentPage); + private static Page GetCurrentPage(this IWindowManager windowManager) + { + var window = windowManager.Current; + if (window is null) + throw new InvalidOperationException("No Window has been set in the Application"); + else if (window is not PrismWindow prismWindow) + throw new InvalidOperationException($"Prism applications only support the use of PrismWindow, but found '{window.GetType().FullName}'."); + else if (prismWindow.CurrentPage is null) + throw new InvalidOperationException("No current page has been set."); + else + return prismWindow.CurrentPage; } } diff --git a/src/Maui/Prism.Maui/Navigation/PrismWindow.cs b/src/Maui/Prism.Maui/Navigation/PrismWindow.cs index a630207f68..2b8e19eccf 100644 --- a/src/Maui/Prism.Maui/Navigation/PrismWindow.cs +++ b/src/Maui/Prism.Maui/Navigation/PrismWindow.cs @@ -20,7 +20,7 @@ public PrismWindow(string name = DefaultWindowName) public string Name { get; } - public bool IsActive { get; private set; } + public bool IsActive { get; internal set; } internal Page CurrentPage => Page is null ? null : MvvmHelpers.GetCurrentPage(Page); diff --git a/src/Maui/Prism.Maui/Navigation/PrismWindowManager.cs b/src/Maui/Prism.Maui/Navigation/PrismWindowManager.cs index 7b95b7a770..617ad1ef6c 100644 --- a/src/Maui/Prism.Maui/Navigation/PrismWindowManager.cs +++ b/src/Maui/Prism.Maui/Navigation/PrismWindowManager.cs @@ -1,4 +1,7 @@ -namespace Prism.Navigation; +using Prism.Behaviors; +using Prism.Extensions; + +namespace Prism.Navigation; internal sealed class PrismWindowManager : IWindowCreator, IWindowManager { @@ -11,6 +14,9 @@ public PrismWindowManager(IApplication application) private Window _initialWindow; + private Window _current; + public Window Current => _current ?? _initialWindow; + public IReadOnlyList Windows => _application.Windows.OfType().ToList(); public Window CreateWindow(Application app, IActivationState activationState) @@ -31,6 +37,11 @@ public void OpenWindow(Window window) _initialWindow = window; else _application.OpenWindow(window); + + foreach(var pWindow in Windows.OfType().Where(x => x.IsActive)) + { + pWindow.IsActive = window.Equals(pWindow); + } } public void CloseWindow(Window window)