Skip to content

Commit

Permalink
feat: support getting the current IDialogService from a Singleton
Browse files Browse the repository at this point in the history
  • Loading branch information
dansiegel committed Feb 28, 2024
1 parent efbd9f7 commit 87a65f3
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 18 deletions.
38 changes: 28 additions & 10 deletions src/Maui/Prism.Maui/Common/MvvmHelpers.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -272,27 +273,44 @@ public static void SetCurrentPageDelegate(Func<Page, Page> 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;
}
Expand Down
25 changes: 24 additions & 1 deletion src/Maui/Prism.Maui/Navigation/IWindowManager.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,33 @@
using System;
namespace Prism.Navigation;

#nullable enable
/// <summary>
/// Defines an interface for managing windows within an application.
/// </summary>
public interface IWindowManager
{
/// <summary>
/// Gets a read-only collection of all currently open windows.
/// </summary>
IReadOnlyList<Window> Windows { get; }

/// <summary>
/// Gets the currently active window, if any.
/// </summary>
Window? Current { get; }

/// <summary>
/// Opens a new window.
/// </summary>
/// <param name="window">The Window object to be opened.</param>
/// <exception cref="ArgumentNullException">Thrown if the window parameter is null.</exception>
void OpenWindow(Window window);

/// <summary>
/// Closes a specified window.
/// </summary>
/// <param name="window">The Window object to be closed.</param>
/// <exception cref="ArgumentNullException">Thrown if the window parameter is null.</exception>
void CloseWindow(Window window);
}

34 changes: 29 additions & 5 deletions src/Maui/Prism.Maui/Navigation/IWindowManagerExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
namespace Prism.Navigation;
using Prism.Dialogs;
using Prism.Navigation.Xaml;

namespace Prism.Navigation;

/// <summary>
/// Provides extensions for the <see cref="IWindowManager"/>
Expand All @@ -12,11 +15,32 @@ public static class IWindowManagerExtensions
/// <returns>The <see cref="INavigationService"/> for the current <see cref="Page"/>.</returns>
public static INavigationService GetCurrentNavigationService(this IWindowManager windowManager)
{
var window = windowManager.Windows.OfType<PrismWindow>().First();
var page = windowManager.GetCurrentPage();
return Xaml.Navigation.GetNavigationService(page);
}

if (window.CurrentPage is null)
throw new InvalidOperationException("No current page has been set.");
/// <summary>
/// Gets the <see cref="IDialogService"/> for the currently displayed <see cref="Page"/>.
/// </summary>
/// <param name="windowManager">The <see cref="IWindowManager"/>.</param>
/// <returns>The <see cref="IDialogService"/> for the current <see cref="Page"/>.</returns>
public static IDialogService GetCurrentDialogService(this IWindowManager windowManager)
{
var page = windowManager.GetCurrentPage();
var container = page.GetContainerProvider();
return container.Resolve<IDialogService>();
}

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;
}
}
2 changes: 1 addition & 1 deletion src/Maui/Prism.Maui/Navigation/PrismWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
13 changes: 12 additions & 1 deletion src/Maui/Prism.Maui/Navigation/PrismWindowManager.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
namespace Prism.Navigation;
using Prism.Behaviors;
using Prism.Extensions;

namespace Prism.Navigation;

internal sealed class PrismWindowManager : IWindowCreator, IWindowManager
{
Expand All @@ -11,6 +14,9 @@ public PrismWindowManager(IApplication application)

private Window _initialWindow;

private Window _current;
public Window Current => _current ?? _initialWindow;

public IReadOnlyList<Window> Windows => _application.Windows.OfType<Window>().ToList();

public Window CreateWindow(Application app, IActivationState activationState)
Expand All @@ -31,6 +37,11 @@ public void OpenWindow(Window window)
_initialWindow = window;
else
_application.OpenWindow(window);

foreach(var pWindow in Windows.OfType<PrismWindow>().Where(x => x.IsActive))
{
pWindow.IsActive = window.Equals(pWindow);
}
}

public void CloseWindow(Window window)
Expand Down

0 comments on commit 87a65f3

Please sign in to comment.