Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,9 @@ FakesAssemblies/

# Binlog
*.binlog

# macOS
.DS_Store

# VSCode
.mono
78 changes: 40 additions & 38 deletions src/Maui/Prism.Maui/Common/MvvmHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#nullable enable
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using Prism.Dialogs;
using Prism.Navigation;
Expand All @@ -11,14 +13,14 @@ namespace Prism.Common;

public static class MvvmHelpers
{
public static void InvokeViewAndViewModelAction<T>(object view, Action<T> action) where T : class
public static void InvokeViewAndViewModelAction<T>(object? view, Action<T> action) where T : class
{
if (view is T viewAsT)
{
action(viewAsT);
}

if (view is BindableObject element && element.BindingContext is T viewModelAsT)
if (view is BindableObject { BindingContext: T viewModelAsT })
{
action(viewModelAsT);
}
Expand All @@ -32,14 +34,14 @@ public static void InvokeViewAndViewModelAction<T>(object view, Action<T> action
}
}

public static async Task InvokeViewAndViewModelActionAsync<T>(object view, Func<T, Task> action) where T : class
public static async Task InvokeViewAndViewModelActionAsync<T>(object? view, Func<T, Task> action) where T : class
{
if (view is T viewAsT)
{
await action(viewAsT);
}

if (view is BindableObject element && element.BindingContext is T viewModelAsT)
if (view is BindableObject { BindingContext: T viewModelAsT })
{
await action(viewModelAsT);
}
Expand All @@ -49,11 +51,11 @@ public static async Task InvokeViewAndViewModelActionAsync<T>(object view, Func<
var children = page.GetChildRegions();
if (children is not null)
foreach (var child in children)
await InvokeViewAndViewModelActionAsync<T>(child, action);
await InvokeViewAndViewModelActionAsync(child, action);
}
}

public static void DestroyPage(IView view)
public static void DestroyPage(IView? view)
{
try
{
Expand Down Expand Up @@ -96,7 +98,7 @@ private static void DestroyChildren(IView page)
}
}

public static void DestroyWithModalStack(Page page, IList<Page> modalStack)
public static void DestroyWithModalStack(Page? page, IList<Page?> modalStack)
{
foreach (var childPage in modalStack.Reverse())
{
Expand All @@ -105,15 +107,15 @@ public static void DestroyWithModalStack(Page page, IList<Page> modalStack)
DestroyPage(page);
}

public static T GetImplementerFromViewOrViewModel<T>(object view)
public static T? GetImplementerFromViewOrViewModel<T>(object view)
where T : class
{
if (view is T viewAsT)
{
return viewAsT;
}

if (view is VisualElement element && element.BindingContext is T vmAsT)
if (view is VisualElement { BindingContext: T vmAsT })
{
return vmAsT;
}
Expand All @@ -136,12 +138,12 @@ public static bool IsNavigationTarget(object view, NavigationContext navigationC
return path == viewType.Name || path == viewType.FullName;
}

public static void OnNavigatedFrom(object view, NavigationContext navigationContext)
public static void OnNavigatedFrom(object? view, NavigationContext navigationContext)
{
InvokeViewAndViewModelAction<IRegionAware>(view, x => x.OnNavigatedFrom(navigationContext));
}

public static void OnNavigatedTo(object view, NavigationContext navigationContext)
public static void OnNavigatedTo(object? view, NavigationContext navigationContext)
{
InvokeViewAndViewModelAction<IRegionAware>(view, x => x.OnNavigatedTo(navigationContext));
}
Expand All @@ -161,35 +163,35 @@ private static bool CanNavigate(object page, INavigationParameters parameters)
return implementer?.CanNavigate(parameters) ?? true;
}

public static void OnNavigatedFrom(object page, INavigationParameters parameters)
public static void OnNavigatedFrom(object? page, INavigationParameters parameters)
{
if (page != null)
InvokeViewAndViewModelAction<INavigatedAware>(page, v => v.OnNavigatedFrom(parameters));
}

public static async Task OnInitializedAsync(object page, INavigationParameters parameters)
public static async Task OnInitializedAsync(object? page, INavigationParameters parameters)
{
if (page is null) return;

InvokeViewAndViewModelAction<IInitialize>(page, v => v.Initialize(parameters));
await InvokeViewAndViewModelActionAsync<IInitializeAsync>(page, async v => await v.InitializeAsync(parameters));
}

private static bool HasKey(this IEnumerable<KeyValuePair<string, object>> parameters, string name, out string key)
private static bool HasKey(this IEnumerable<KeyValuePair<string, object>> parameters, string name, [MaybeNullWhen(returnValue: false)] out string key)
{
key = parameters.Select(x => x.Key).FirstOrDefault(k => k.Equals(name, StringComparison.InvariantCultureIgnoreCase));
return !string.IsNullOrEmpty(key);
}

public static void OnNavigatedTo(object page, INavigationParameters parameters)
public static void OnNavigatedTo(object? page, INavigationParameters parameters)
{
if (page != null)
InvokeViewAndViewModelAction<INavigatedAware>(page, v => v.OnNavigatedTo(parameters));
}

public static Page GetOnNavigatedToTarget(Page page, IView mainPage, bool useModalNavigation)
public static Page? GetOnNavigatedToTarget(Page page, IView? mainPage, bool useModalNavigation)
{
Page target;
Page? target;
if (useModalNavigation)
{
var previousPage = GetPreviousPage(page, page.Navigation.ModalStack);
Expand All @@ -210,9 +212,9 @@ public static Page GetOnNavigatedToTarget(Page page, IView mainPage, bool useMod
return target;
}

public static Page GetOnNavigatedToTargetFromChild(IView target)
public static Page? GetOnNavigatedToTargetFromChild(IView? target)
{
Page child = null;
Page? child = null;

if (target is FlyoutPage flyout)
child = flyout.Detail;
Expand All @@ -230,9 +232,9 @@ public static Page GetOnNavigatedToTargetFromChild(IView target)
return null;
}

public static Page GetPreviousPage(Page currentPage, System.Collections.Generic.IReadOnlyList<Page> navStack)
public static Page? GetPreviousPage(Page currentPage, IReadOnlyList<Page?> navStack)
{
Page previousPage = null;
Page? previousPage = null;

int currentPageIndex = GetCurrentPageIndex(currentPage, navStack);
int previousPageIndex = currentPageIndex - 1;
Expand All @@ -242,7 +244,7 @@ public static Page GetPreviousPage(Page currentPage, System.Collections.Generic.
return previousPage;
}

public static int GetCurrentPageIndex(Page currentPage, System.Collections.Generic.IReadOnlyList<Page> navStack)
public static int GetCurrentPageIndex(Page currentPage, IReadOnlyList<Page?> navStack)
{
int stackCount = navStack.Count;
for (int x = 0; x < stackCount; x++)
Expand All @@ -255,14 +257,14 @@ public static int GetCurrentPageIndex(Page currentPage, System.Collections.Gener
return stackCount - 1;
}

public static Page GetCurrentPage(Page mainPage) =>
public static Page? GetCurrentPage(Page mainPage) =>
_getCurrentPage(mainPage);

[EditorBrowsable(EditorBrowsableState.Never)]
public static void SetCurrentPageDelegate(Func<Page, Page> getCurrentPageDelegate) =>
public static void SetCurrentPageDelegate(Func<Page, Page?> getCurrentPageDelegate) =>
_getCurrentPage = getCurrentPageDelegate;

private static Func<Page, Page> _getCurrentPage = mainPage =>
private static Func<Page, Page?> _getCurrentPage = mainPage =>
{
var page = mainPage;

Expand All @@ -273,7 +275,7 @@ public static void SetCurrentPageDelegate(Func<Page, Page> getCurrentPageDelegat
return EvaluateCurrentPage(page);
};

private static Page GetTarget(Page target)
private static Page? GetTarget(Page? target)
{
return target switch
{
Expand All @@ -285,14 +287,14 @@ private static Page GetTarget(Page target)
};
}

private static Page EvaluateCurrentPage(Page target)
private static Page? EvaluateCurrentPage(Page? target)
{
Page child = GetTarget(target);
Page? child = GetTarget(target);

if (child is not null)
target = GetOnNavigatedToTargetFromChild(child);

if (target is Page page)
if (target is { } page)
{
if (target is IDialogContainer)
{
Expand All @@ -319,9 +321,9 @@ public static async Task HandleNavigationPageGoBack(NavigationPage navigationPag
{
var navigationService = Navigation.Xaml.Navigation.GetNavigationService(navigationPage.CurrentPage);
var result = await navigationService.GoBackAsync();
if (result.Exception is NavigationException navEx && navEx.Message == NavigationException.CannotPopApplicationMainPage)
if (result.Exception is NavigationException { Message: NavigationException.CannotPopApplicationMainPage })
{
Application.Current.Quit();
Application.Current?.Quit();
}
}

Expand All @@ -335,13 +337,13 @@ public static async Task HandleNavigationPageSwipedAway(NavigationPage navigatio
},
};
var result = await navigationService.GoBackAsync(navParams);
if (result.Exception is NavigationException navEx && navEx.Message == NavigationException.CannotPopApplicationMainPage)
if (result.Exception is NavigationException { Message: NavigationException.CannotPopApplicationMainPage })
{
Application.Current.Quit();
Application.Current?.Quit();
}
}

public static void HandleSystemGoBack(IView previousPage, IView currentPage)
public static void HandleSystemGoBack(IView? previousPage, IView? currentPage)
{
var parameters = new NavigationParameters();
parameters.GetNavigationParametersInternal().Add(KnownInternalParameters.NavigationMode, NavigationMode.Back);
Expand All @@ -352,22 +354,22 @@ public static void HandleSystemGoBack(IView previousPage, IView currentPage)

internal static bool HasDirectNavigationPageParent(Page page)
{
return page?.Parent != null && page?.Parent is NavigationPage;
return page.Parent is NavigationPage;
}

internal static bool HasNavigationPageParent(Page page) =>
HasNavigationPageParent(page, out var _);

internal static bool HasNavigationPageParent(Page page, out NavigationPage navigationPage)
internal static bool HasNavigationPageParent(Page page, out NavigationPage? navigationPage)
{
if (page?.Parent != null)
if (page.Parent != null)
{
if (page.Parent is NavigationPage navParent)
{
navigationPage = navParent;
return true;
}
else if ((page.Parent is TabbedPage) && page.Parent?.Parent is NavigationPage navigationParent)
else if (page.Parent is TabbedPage && page.Parent?.Parent is NavigationPage navigationParent)
{
navigationPage = navigationParent;
return true;
Expand Down
2 changes: 1 addition & 1 deletion src/Prism.Core/Navigation/NavigationResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public NavigationResult(bool success)
/// Initializes a new NavigationResult with an <see cref="Exception"/>
/// </summary>
/// <param name="ex">The <see cref="Exception"/> encountered as part of the navigation.</param>
public NavigationResult(Exception ex)
public NavigationResult(Exception? ex)
{
Exception = ex;
}
Expand Down