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

Add HandlerProperties.DisconnectPolicy for controlling when DisconnectHandler is called #23738

Merged
merged 22 commits into from
Jul 25, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -890,7 +890,7 @@ async Task UpdateFormsInnerNavigation(Page pageBeingRemoved)
await (NavPage as INavigationPageController)?.RemoveAsyncInner(pageBeingRemoved, false, true);
if (_uiRequestedPop)
{
NavPage?.SendNavigatedFromHandler(pageBeingRemoved);
NavPage?.SendNavigatedFromHandler(pageBeingRemoved, NavigationType.Pop);
}
}

Expand Down Expand Up @@ -1097,8 +1097,8 @@ public override void DidShowViewController(UINavigationController navigationCont

if (r.Element is NavigationPage np && !_finishedWithInitialNavigation)
{
_finishedWithInitialNavigation = true;
np.SendNavigatedFromHandler(null);
_finishedWithInitialNavigation = true;
np.SendNavigatedFromHandler(null, NavigationType.Push);
}

if (WaitingForNavigationToFinish)
Expand Down Expand Up @@ -1969,7 +1969,7 @@ protected override void Dispose(bool disposing)
if (disposing)
{

if (_child != null)
if (_child?.IsConnected() == true)
{
_child.PlatformView.RemoveFromSuperview();
_child.DisconnectHandler();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,19 +68,25 @@ void IFlyoutBehaviorObserver.OnFlyoutBehaviorChanged(FlyoutBehavior behavior)
DrawerArrowDrawable _drawerArrowDrawable;
FlyoutIconDrawerDrawable _flyoutIconDrawerDrawable;
IToolbar _toolbar;
protected IMauiContext MauiContext => ShellContext.Shell.Handler.MauiContext;
protected IMauiContext MauiContext => _shell.Handler.MauiContext;

Toolbar _shellRootToolBar;
Shell _shell;

public ShellToolbarTracker(IShellContext shellContext, AToolbar toolbar, DrawerLayout drawerLayout)
{
ShellContext = shellContext ?? throw new ArgumentNullException(nameof(shellContext));
_shell = shellContext.Shell;

_platformToolbar = toolbar ?? throw new ArgumentNullException(nameof(toolbar));
_drawerLayout = drawerLayout ?? throw new ArgumentNullException(nameof(drawerLayout));
_appBar = _platformToolbar.Parent.GetParentOfType<AppBarLayout>();

_globalLayoutListener = new GenericGlobalLayoutListener((_, _) => UpdateNavBarHasShadow(Page), _appBar);
_platformToolbar.SetNavigationOnClickListener(this);
((IShellController)ShellContext.Shell).AddFlyoutBehaviorObserver(this);
ShellContext.Shell.Toolbar.PropertyChanged += OnToolbarPropertyChanged;
_shellRootToolBar = _shell.Toolbar;
_shellRootToolBar.PropertyChanged += OnToolbarPropertyChanged;
ShellContext.Shell.Navigated += OnShellNavigated;
ShellContext.Shell.PropertyChanged += HandleShellPropertyChanged;
}
Expand Down Expand Up @@ -162,7 +168,7 @@ void AView.IOnClickListener.OnClick(AView v)
else if (CanNavigateBack)
OnNavigateBack();
else
ShellContext.Shell.FlyoutIsPresented = !ShellContext.Shell.FlyoutIsPresented;
_shell.FlyoutIsPresented = !_shell.FlyoutIsPresented;
}
}

Expand All @@ -181,9 +187,9 @@ protected override void Dispose(bool disposing)
_backButtonBehavior.PropertyChanged -= OnBackButtonBehaviorChanged;

((IShellController)ShellContext.Shell)?.RemoveFlyoutBehaviorObserver(this);
ShellContext.Shell.Toolbar.PropertyChanged -= OnToolbarPropertyChanged;
ShellContext.Shell.Navigated -= OnShellNavigated;
ShellContext.Shell.PropertyChanged -= HandleShellPropertyChanged;
_shellRootToolBar.PropertyChanged -= OnToolbarPropertyChanged;
_shell.Navigated -= OnShellNavigated;
_shell.PropertyChanged -= HandleShellPropertyChanged;
UpdateTitleView(ShellContext.AndroidContext, _platformToolbar, null);

if (_searchView != null)
Expand Down Expand Up @@ -212,6 +218,7 @@ protected override void Dispose(bool disposing)
_platformToolbar = null;
_appBar = null;
_drawerLayout = null;
_shell = null;

base.Dispose(disposing);
}
Expand Down Expand Up @@ -261,8 +268,8 @@ protected virtual void OnPageChanged(Page oldPage, Page newPage)
UpdateNavBarHasShadow(newPage);
UpdateTitleView();

if (ShellContext.Shell.Toolbar is ShellToolbar shellToolbar &&
newPage == ShellContext.Shell.GetCurrentShellPage())
if (_shell.Toolbar is ShellToolbar shellToolbar &&
newPage == _shell.GetCurrentShellPage())
{
shellToolbar.ApplyChanges();
}
Expand All @@ -274,8 +281,8 @@ void OnShellNavigated(object sender, ShellNavigatedEventArgs e)
if (_disposed || Page == null)
return;

if (ShellContext?.Shell?.Toolbar is ShellToolbar &&
Page == ShellContext?.Shell?.GetCurrentShellPage())
if (_shell?.Toolbar is ShellToolbar &&
Page == _shell?.GetCurrentShellPage())
{
UpdateLeftBarButtonItem();
UpdateTitleView();
Expand Down Expand Up @@ -402,7 +409,7 @@ protected virtual async void UpdateLeftBarButtonItem(Context context, AToolbar t
var backButtonHandler = Shell.GetBackButtonBehavior(page);
var text = backButtonHandler.GetPropertyIfSet(BackButtonBehavior.TextOverrideProperty, String.Empty);
var command = backButtonHandler.GetPropertyIfSet<ICommand>(BackButtonBehavior.CommandProperty, null);
bool isEnabled = ShellContext.Shell.Toolbar.BackButtonEnabled;
bool isEnabled = _shell.Toolbar.BackButtonEnabled;
var image = GetFlyoutIcon(backButtonHandler, page);
var backButtonVisible = _toolbar.BackButtonVisible;

Expand Down Expand Up @@ -496,7 +503,7 @@ protected virtual async void UpdateLeftBarButtonItem(Context context, AToolbar t


//this needs to be set after SyncState
UpdateToolbarIconAccessibilityText(toolbar, ShellContext.Shell);
UpdateToolbarIconAccessibilityText(toolbar, _shell);
_toolbar?.Handler?.UpdateValue(nameof(Toolbar.IconColor));
}

Expand Down Expand Up @@ -604,10 +611,10 @@ void UpdateNavBarHasShadow(Page page)

void OnToolbarPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (_toolbar != null && ShellContext?.Shell?.GetCurrentShellPage() == Page)
if (_toolbar != null && _shell?.GetCurrentShellPage() == Page)
{
ApplyToolbarChanges((Toolbar)sender, (Toolbar)_toolbar);
UpdateToolbarIconAccessibilityText(_platformToolbar, ShellContext.Shell);
UpdateToolbarIconAccessibilityText(_platformToolbar, _shell);
}
}

Expand All @@ -617,7 +624,7 @@ protected virtual void UpdatePageTitle(AToolbar toolbar, Page page)

protected virtual void UpdateTitleView(Context context, AToolbar toolbar, View titleView)
{
if (_toolbar != null && ShellContext?.Shell?.GetCurrentShellPage() == Page)
if (_toolbar != null && _shell?.GetCurrentShellPage() == Page)
_toolbar.Handler?.UpdateValue(nameof(Toolbar.TitleView));
}

Expand Down
8 changes: 7 additions & 1 deletion src/Controls/src/Core/Element/Element.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ namespace Microsoft.Maui.Controls
/// </item>
/// </list>
///</remarks>
public abstract partial class Element : BindableObject, IElementDefinition, INameScope, IElementController, IVisualTreeElement, Maui.IElement, IEffectControlProvider, IToolTipElement, IContextFlyoutElement, IControlsElement
public abstract partial class Element : BindableObject, IElementDefinition, INameScope, IElementController, IVisualTreeElement, Maui.IElement, IEffectControlProvider, IToolTipElement, IContextFlyoutElement, IControlsElement, IHandlerDisconnectPolicies
{
internal static readonly ReadOnlyCollection<Element> EmptyChildren = new ReadOnlyCollection<Element>(Array.Empty<Element>());

Expand Down Expand Up @@ -1026,6 +1026,12 @@ void IEffectControlProvider.RegisterEffect(Effect effect)
/// <inheritdoc/>
IFlyout IContextFlyoutElement.ContextFlyout => FlyoutBase.GetContextFlyout(this);

HandlerDisconnectPolicy IHandlerDisconnectPolicies.DisconnectPolicy
{
get => HandlerProperties.GetDisconnectPolicy(this);
set => HandlerProperties.SetDisconnectPolicy(this, value);
}

class TemporaryWrapper : IList<Element>
{
IReadOnlyList<Element> _inner;
Expand Down
4 changes: 2 additions & 2 deletions src/Controls/src/Core/FlyoutPage/FlyoutPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public Page Detail
_detail?.SendAppearing();
}

previousDetail?.SendNavigatedFrom(new NavigatedFromEventArgs(_detail));
previousDetail?.SendNavigatedFrom(new NavigatedFromEventArgs(_detail, NavigationType.PageSwap));
_detail?.SendNavigatedTo(new NavigatedToEventArgs(previousDetail));
}
}
Expand Down Expand Up @@ -121,7 +121,7 @@ public Page Flyout
_flyout?.SendAppearing();
}

previousFlyout?.SendNavigatedFrom(new NavigatedFromEventArgs(_flyout));
previousFlyout?.SendNavigatedFrom(new NavigatedFromEventArgs(_flyout, NavigationType.PageSwap));
_flyout?.SendNavigatedTo(new NavigatedToEventArgs(previousFlyout));
}
}
Expand Down
23 changes: 23 additions & 0 deletions src/Controls/src/Core/Handlers/HandlerProperties.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Microsoft.Maui;

namespace Microsoft.Maui.Controls
{
public static class HandlerProperties
{
public static readonly BindableProperty DisconnectPolicyProperty = BindableProperty.CreateAttached(
"DisconnectPolicy",
typeof(HandlerDisconnectPolicy),
typeof(HandlerProperties),
HandlerDisconnectPolicy.Automatic);

public static void SetDisconnectPolicy(BindableObject target, HandlerDisconnectPolicy value)
{
target.SetValue(DisconnectPolicyProperty, value);
}

public static HandlerDisconnectPolicy GetDisconnectPolicy(BindableObject target)
{
return (HandlerDisconnectPolicy)target.GetValue(DisconnectPolicyProperty);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,8 @@ protected override void DisconnectHandler(ListViewBase platformView)
if (ItemsView != null)
ItemsView.Scrolled -= CarouselScrolled;

if (ListViewBase != null)
{
ListViewBase.SizeChanged -= OnListViewSizeChanged;
_proxy.Unsubscribe();
}
platformView.SizeChanged -= OnListViewSizeChanged;
_proxy.Unsubscribe();

if (_scrollViewer != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,6 @@ ShellItemHandler CreateShellItemView()
}

void TabSelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args) =>
Element.Handler.UpdateValue(nameof(Shell.CurrentItem));
Element?.Handler?.UpdateValue(nameof(Shell.CurrentItem));
}
}
2 changes: 1 addition & 1 deletion src/Controls/src/Core/MultiPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public T CurrentPage
if (HasAppeared)
_current?.SendAppearing();

previousPage?.SendNavigatedFrom(new NavigatedFromEventArgs(_current));
previousPage?.SendNavigatedFrom(new NavigatedFromEventArgs(_current, NavigationType.PageSwap));
_current?.SendNavigatedTo(new NavigatedToEventArgs(previousPage));
}
}
Expand Down
10 changes: 5 additions & 5 deletions src/Controls/src/Core/NavigationPage/NavigationPage.Legacy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ async Task<Page> PopAsyncInner(
var previousPage = CurrentPage;
SendNavigating();
var removedPage = await RemoveAsyncInner(page, animated, fast);
SendNavigated(previousPage);
SendNavigated(previousPage, NavigationType.Pop);
return removedPage;
}

Expand Down Expand Up @@ -174,7 +174,7 @@ async Task PopToRootAsyncInner(bool animated)
}

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

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

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

Expand All @@ -209,12 +209,12 @@ async Task PushAsyncInner(Page page, bool animated)
// there are scenarios where the legacy handler needs to alert the xplat
// code of when a navigation has occurred.
// For example, initial load and when the user taps the back button
internal void SendNavigatedFromHandler(Page previousPage)
internal void SendNavigatedFromHandler(Page previousPage, NavigationType navigationType)
{
if (CurrentPage.HasNavigatedTo)
return;

SendNavigated(previousPage);
SendNavigated(previousPage, navigationType);
}
#endif

Expand Down
13 changes: 7 additions & 6 deletions src/Controls/src/Core/NavigationPage/NavigationPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -374,9 +374,9 @@ protected override bool OnBackButtonPressed()
return base.OnBackButtonPressed();
}

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

Expand Down Expand Up @@ -699,7 +699,8 @@ private protected override void OnHandlerChangedCore()
},
() =>
{
SendNavigated(null);
// TODO this is the wrong navigation type
SendNavigated(null, NavigationType.Initialize);
})
.FireAndForget(Handler);
}
Expand Down Expand Up @@ -797,7 +798,7 @@ await Owner.SendHandlerUpdateAsync(animated,
},
() =>
{
Owner.SendNavigated(currentPage);
Owner.SendNavigated(currentPage, NavigationType.Pop);
Owner?.Popped?.Invoke(Owner, new NavigationEventArgs(currentPage));
});

Expand Down Expand Up @@ -834,7 +835,7 @@ protected override Task OnPopToRootAsync(bool animated)
},
() =>
{
Owner.SendNavigated(previousPage);
Owner.SendNavigated(previousPage, NavigationType.PopToRoot);
Owner?.PoppedToRoot?.Invoke(Owner, new PoppedToRootEventArgs(newPage, pagesToRemove));
});
}
Expand All @@ -859,7 +860,7 @@ protected override Task OnPushAsync(Page root, bool animated)
},
() =>
{
Owner.SendNavigated(previousPage);
Owner.SendNavigated(previousPage, NavigationType.Push);
Owner?.Pushed?.Invoke(Owner, new NavigationEventArgs(root));
});
}
Expand Down
21 changes: 18 additions & 3 deletions src/Controls/src/Core/Page/NavigatedFromEventArgs.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,30 @@
#nullable disable
using System;
using Microsoft.Maui.Controls.Internals;

namespace Microsoft.Maui.Controls
{
internal enum NavigationType
{
Push,
Pop,
PopToRoot,
Insert,
Remove,
PageSwap,
Initialize
}

public sealed class NavigatedFromEventArgs : EventArgs
{
internal NavigatedFromEventArgs(Page destinationPage)
internal NavigationType NavigationType { get; }

internal Page DestinationPage { get; }

internal NavigatedFromEventArgs(Page destinationPage, NavigationType navigationType)
{
DestinationPage = destinationPage;
NavigationType = navigationType;
}

internal Page DestinationPage { get; }
}
}
Loading
Loading