Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Navigation Events #1812

Merged
merged 10 commits into from
Jul 27, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,8 @@ void OnUnloaded(object sender, RoutedEventArgs args)

void PushExistingNavigationStack()
{
foreach (var page in Element.Pages)
INavigationPageController navigationPageController = Element;
foreach (var page in navigationPageController.Pages)
{
SetPage(page, false, false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public NavigationRenderer() : base(typeof(FormsNavigationBar), null)
IPageController PageController => Element as IPageController;

NavigationPage NavPage => Element as NavigationPage;
INavigationPageController NavPageController => NavPage;

public VisualElement Element { get; private set; }

Expand Down Expand Up @@ -237,7 +238,7 @@ public override void ViewDidLoad()
SetNeedsUpdateOfHomeIndicatorAutoHidden();

// If there is already stuff on the stack we need to push it
navPage.Pages.ForEach(async p => await PushPageAsync(p, false));
NavPageController.Pages.ForEach(async p => await PushPageAsync(p, false));

_tracker = new VisualElementTracker(this);

Expand Down Expand Up @@ -1218,7 +1219,7 @@ internal void UpdateLeftBarButtonItem(Page pageBeingRemoved = null)
return;

var currentChild = this.Child;
var firstPage = n.NavPage.Pages.FirstOrDefault();
var firstPage = n.NavPageController.Pages.FirstOrDefault();


if (n._parentFlyoutPage == null)
Expand Down
15 changes: 15 additions & 0 deletions src/Controls/src/Core/FlyoutPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,19 @@ public Page Detail
if (value.RealParent != null)
throw new InvalidOperationException("Detail must not already have a parent.");

var previousDetail = _detail;
// TODO MAUI refine this to fire earlier
_detail?.SendNavigatingFrom(new NavigatingFromEventArgs());

OnPropertyChanging();
if (_detail != null)
InternalChildren.Remove(_detail);
_detail = value;
InternalChildren.Add(_detail);
OnPropertyChanged();

previousDetail?.SendNavigatedFrom(new NavigatedFromEventArgs(_detail));
_detail?.SendNavigatedTo(new NavigatedToEventArgs(previousDetail));
}
}

Expand Down Expand Up @@ -78,12 +85,20 @@ public Page Flyout
if (value.RealParent != null)
throw new InvalidOperationException("Flyout must not already have a parent.");

// TODO MAUI refine this to fire earlier
var previousFlyout = _flyout;
// TODO MAUI refine this to fire earlier
_flyout?.SendNavigatingFrom(new NavigatingFromEventArgs());

OnPropertyChanging();
if (_flyout != null)
InternalChildren.Remove(_flyout);
_flyout = value;
InternalChildren.Add(_flyout);
OnPropertyChanged();

previousFlyout?.SendNavigatedFrom(new NavigatedFromEventArgs(_flyout));
_flyout?.SendNavigatedTo(new NavigatedToEventArgs(previousFlyout));
}
}

Expand Down
54 changes: 53 additions & 1 deletion src/Controls/src/Core/HandlerImpl/Page.Impl.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.Maui.Controls.Internals;
using System;
using Microsoft.Maui.Controls.Internals;
using Microsoft.Maui.Graphics;

namespace Microsoft.Maui.Controls
Expand All @@ -9,5 +10,56 @@ public partial class Page : IPage

// TODO ezhart super sus
public Thickness Margin => Thickness.Zero;

internal void SendNavigatedTo(NavigatedToEventArgs args)
{
NavigatedTo?.Invoke(this, args);
OnNavigatedTo(args);
}

internal void SendNavigatingFrom(NavigatingFromEventArgs args)
{
NavigatingFrom?.Invoke(this, args);
OnNavigatingFrom(args);
}

internal void SendNavigatedFrom(NavigatedFromEventArgs args)
{
NavigatedFrom?.Invoke(this, args);
OnNavigatedFrom(args);
}

public event EventHandler<NavigatedToEventArgs> NavigatedTo;
public event EventHandler<NavigatingFromEventArgs> NavigatingFrom;
public event EventHandler<NavigatedFromEventArgs> NavigatedFrom;

protected virtual void OnNavigatedTo(NavigatedToEventArgs args) { }
protected virtual void OnNavigatingFrom(NavigatingFromEventArgs args) { }
protected virtual void OnNavigatedFrom(NavigatedFromEventArgs args) { }
}

public sealed class NavigatingFromEventArgs : EventArgs
{

}

public sealed class NavigatedToEventArgs : EventArgs
{
internal NavigatedToEventArgs(Page previousPage)
{
PreviousPage = previousPage;
}

internal Page PreviousPage { get; }
}

public sealed class NavigatedFromEventArgs : EventArgs
{
internal NavigatedFromEventArgs(Page destinationPage)
{
DestinationPage = destinationPage;
}

internal Page DestinationPage { get; }
}
}
22 changes: 22 additions & 0 deletions src/Controls/src/Core/HandlerImpl/Window.Impl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -263,9 +263,24 @@ protected override IReadOnlyList<Page> GetModalStack()
return null;
}

modal.SendNavigatingFrom(new NavigatingFromEventArgs());
Page? nextPage;
if (modal.NavigationProxy.ModalStack.Count == 1)
{
nextPage = _owner.Page;
}
else
{
nextPage = _owner.ModalNavigationManager.ModalStack[_owner.ModalNavigationManager.ModalStack.Count - 2];
}

Page result = await _owner.ModalNavigationManager.PopModalAsync(animated);
result.Parent = null;
_owner.OnModalPopped(result);

modal.SendNavigatedFrom(new NavigatedFromEventArgs(nextPage));
nextPage?.SendNavigatedTo(new NavigatedToEventArgs(modal));

return result;
}

Expand All @@ -277,13 +292,20 @@ protected override async Task OnPushModal(Page modal, bool animated)

if (modal.NavigationProxy.ModalStack.Count == 0)
{
_owner.Page?.SendNavigatingFrom(new NavigatingFromEventArgs());
modal.NavigationProxy.Inner = this;
await _owner.ModalNavigationManager.PushModalAsync(modal, animated);
_owner.Page?.SendNavigatedFrom(new NavigatedFromEventArgs(modal));
modal.SendNavigatedTo(new NavigatedToEventArgs(_owner.Page));
}
else
{
var previousModalPage = modal.NavigationProxy.ModalStack[modal.NavigationProxy.ModalStack.Count - 1];
previousModalPage.SendNavigatingFrom(new NavigatingFromEventArgs());
await _owner.ModalNavigationManager.PushModalAsync(modal, animated);
modal.NavigationProxy.Inner = this;
previousModalPage.SendNavigatedFrom(new NavigatedFromEventArgs(modal));
modal.SendNavigatedTo(new NavigatedToEventArgs(previousModalPage));
}

_owner.OnModalPushed(modal);
Expand Down
8 changes: 8 additions & 0 deletions src/Controls/src/Core/MultiPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,18 @@ public T CurrentPage
if (_current == value)
return;

var previousPage = _current;
OnPropertyChanging();

// TODO MAUI refine this to fire earlier
_current?.SendNavigatingFrom(new NavigatingFromEventArgs());

_current = value;
OnPropertyChanged();
OnCurrentPageChanged();

previousPage?.SendNavigatedFrom(new NavigatedFromEventArgs(_current));
_current?.SendNavigatedTo(new NavigatedToEventArgs(previousPage));
}
}

Expand Down
33 changes: 29 additions & 4 deletions src/Controls/src/Core/NavigationPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,7 @@ public Page Peek(int depth)
return (Page)InternalChildren[InternalChildren.Count - depth - 1];
}

[EditorBrowsable(EditorBrowsableState.Never)]
public IEnumerable<Page> Pages => InternalChildren.Cast<Page>();
IEnumerable<Page> INavigationPageController.Pages => InternalChildren.Cast<Page>();

int INavigationPageController.StackDepth
{
Expand Down Expand Up @@ -238,7 +237,7 @@ public async Task PushAsync(Page page, bool animated)
tcs.SetResult(true);
return;
}

CurrentNavigationTask = PushAsyncInner(page, animated);
await CurrentNavigationTask;
}
Expand Down Expand Up @@ -298,6 +297,10 @@ protected override bool OnBackButtonPressed()
remove => _insertPageBeforeRequested -= value;
}

internal void InitialNativeNavigationStackLoaded()
{
SendNavigated(null);
}

internal async Task<Page> PopAsyncInner(
bool animated,
Expand All @@ -310,7 +313,11 @@ protected override bool OnBackButtonPressed()
}

var page = (Page)InternalChildren.Last();
return await RemoveAsyncInner(page, animated, fast, requestedFromHandler);
var previousPage = CurrentPage;
SendNavigating();
var removedPage = await RemoveAsyncInner(page, animated, fast, requestedFromHandler);
SendNavigated(previousPage);
return removedPage;
}

internal async Task<Page> RemoveAsyncInner(
Expand Down Expand Up @@ -355,6 +362,18 @@ protected override bool OnBackButtonPressed()
return page;
}

void SendNavigated(Page previousPage)
{
previousPage?.SendNavigatedFrom(new NavigatedFromEventArgs(CurrentPage));
CurrentPage.SendNavigatedTo(new NavigatedToEventArgs(previousPage));
}

void SendNavigating()
{
CurrentPage?.SendNavigatingFrom(new NavigatingFromEventArgs());
}


Task<Page> INavigationPageController.PopAsyncInner(bool animated, bool fast)
{
return PopAsyncInner(animated, fast, false);
Expand Down Expand Up @@ -409,6 +428,8 @@ async Task PopToRootAsyncInner(bool animated)
if (NavigationPageController.StackDepth == 1)
return;

var previousPage = CurrentPage;
SendNavigating();
FireDisappearing(CurrentPage);
FireAppearing((Page)InternalChildren[0]);

Expand All @@ -430,6 +451,7 @@ async Task PopToRootAsyncInner(bool animated)
}

PoppedToRoot?.Invoke(this, new PoppedToRootEventArgs(RootPage, childrenToRemove.OfType<Page>().ToList()));
SendNavigated(previousPage);
}

void FireDisappearing(Page page)
Expand All @@ -449,6 +471,8 @@ async Task PushAsyncInner(Page page, bool animated)
if (InternalChildren.Contains(page))
return;

var previousPage = CurrentPage;
SendNavigating();
FireDisappearing(CurrentPage);
FireAppearing(page);

Expand All @@ -465,6 +489,7 @@ async Task PushAsyncInner(Page page, bool animated)
await args.Task;
}

SendNavigated(previousPage);
Pushed?.Invoke(this, args);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,24 @@
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Maui.Controls.Internals;

namespace Microsoft.Maui.Controls.Platform
{
internal partial class ModalNavigationManager
{
public Task<Page> PopModalAsync(bool animated)
{
throw new NotImplementedException();
if (ModalStack.Count == 0)
throw new InvalidOperationException();

return Task.FromResult(_navModel.PopModal());
}

public Task PushModalAsync(Page modal, bool animated)
{
throw new NotImplementedException();
_navModel.PushModal(modal);
return Task.CompletedTask;
}
}
}
2 changes: 1 addition & 1 deletion src/Controls/src/Core/Routing.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ internal static void RegisterImplicitPageRoutes(Shell shell)
var page = section.Navigation.ModalStack[i];
RegisterImplicitPageRoute(page);

if (page is NavigationPage np)
if (page is INavigationPageController np)
{
foreach (var npPages in np.Pages)
{
Expand Down
36 changes: 25 additions & 11 deletions src/Controls/src/Core/Shell/Shell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,7 @@ public void RemoveLogicalChild(Element element)
View _flyoutFooterView;
ShellNavigationManager _navigationManager;
ShellFlyoutItemsManager _flyoutManager;
Page _previousPage;

ObservableCollection<Element> _logicalChildren = new ObservableCollection<Element>();

Expand All @@ -591,17 +592,8 @@ public void RemoveLogicalChild(Element element)
public Shell()
{
_navigationManager = new ShellNavigationManager(this);
_navigationManager.Navigated += (_, args) =>
{
OnNavigated(args);
Navigated?.Invoke(this, args);
};

_navigationManager.Navigating += (_, args) =>
{
Navigating?.Invoke(this, args);
OnNavigating(args);
};
_navigationManager.Navigated += (_, args) => SendNavigated(args);
_navigationManager.Navigating += (_, args) => SendNavigating(args);

_flyoutManager = new ShellFlyoutItemsManager(this);
Navigation = new NavigationImpl(this);
Expand Down Expand Up @@ -892,6 +884,28 @@ async void NavigationPop()

bool ValidDefaultShellItem(Element child) => !(child is MenuShellItem);

void SendNavigated(ShellNavigatedEventArgs args)
{
Navigated?.Invoke(this, args);
OnNavigated(args);

_previousPage?.SendNavigatedFrom(new NavigatedFromEventArgs(CurrentPage));
CurrentPage?.SendNavigatedTo(new NavigatedToEventArgs(_previousPage));
_previousPage = null;
}

void SendNavigating(ShellNavigatingEventArgs args)
{
Navigating?.Invoke(this, args);
OnNavigating(args);

if (!args.Cancelled)
{
_previousPage = CurrentPage;
CurrentPage?.SendNavigatingFrom(new NavigatingFromEventArgs());
}
}

protected virtual void OnNavigated(ShellNavigatedEventArgs args)
{
}
Expand Down