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

Fix For Maui Navigation cast Type A to Type B #3581

Merged
merged 2 commits into from
Jul 11, 2023
Merged
Changes from 1 commit
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
31 changes: 24 additions & 7 deletions src/ReactiveUI.Maui/RoutedViewHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// See the LICENSE file in the project root for full license information.

using System;
using System.Collections.Specialized;
using System.Reactive;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
Expand Down Expand Up @@ -40,6 +41,8 @@ public class RoutedViewHost : NavigationPage, IActivatableView, IEnableLogger
typeof(RoutedViewHost),
false);

private string? _action;

/// <summary>
/// Initializes a new instance of the <see cref="RoutedViewHost"/> class.
/// </summary>
Expand All @@ -50,6 +53,13 @@ public RoutedViewHost()
{
var currentlyNavigating = false;

Observable.FromEventPattern<NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>(
x => Router!.NavigationStack.CollectionChanged += x,
x => Router!.NavigationStack.CollectionChanged -= x)
.Where(_ => !currentlyNavigating && Router?.NavigationStack.Count == 0)
.Subscribe(async _ => await SyncNavigationStacksAsync())
.DisposeWith(disposable);

Router?
.NavigateBack
.Subscribe(async _ =>
Expand All @@ -64,6 +74,7 @@ public RoutedViewHost()
currentlyNavigating = false;
}

_action = "NavigatedBack";
InvalidateCurrentViewModel();
await SyncNavigationStacksAsync();
})
Expand Down Expand Up @@ -108,8 +119,7 @@ public RoutedViewHost()
x => Popped += x,
x => Popped -= x);

// NB: Catch when the user hit back as opposed to the application
// requesting Back via NavigateBack
// NB: User pressed the Application back as opposed to requesting Back via Router.NavigateBack.
poppingEvent
.Where(_ => !currentlyNavigating && Router is not null)
.Subscribe(_ =>
Expand All @@ -119,6 +129,7 @@ public RoutedViewHost()
Router.NavigationStack.RemoveAt(Router.NavigationStack.Count - 1);
}

_action = "Popped";
InvalidateCurrentViewModel();
})
.DisposeWith(disposable);
Expand All @@ -132,8 +143,6 @@ public RoutedViewHost()
x => PoppedToRoot += x,
x => PoppedToRoot -= x);

// NB: Catch when the user hit back as opposed to the application
// requesting Back via NavigateBack
poppingToRootEvent
.Where(_ => !currentlyNavigating && Router is not null)
.Subscribe(_ =>
Expand All @@ -146,6 +155,7 @@ public RoutedViewHost()
}
}

_action = "PoppedToRoot";
InvalidateCurrentViewModel();
})
.DisposeWith(disposable);
Expand Down Expand Up @@ -183,7 +193,7 @@ protected virtual IObservable<Page> PagesForViewModel(IRoutableViewModel? vm)
{
if (vm is null)
{
return Observable<Page>.Empty;
return Observable.Empty<Page>();
}

var ret = ViewLocator.Current.ResolveView(vm);
Expand Down Expand Up @@ -245,8 +255,15 @@ protected void InvalidateCurrentViewModel()
var vm = Router?.GetCurrentViewModel();
if (CurrentPage is IViewFor page && vm is not null)
{
// don't replace view model if vm is null
page.ViewModel = vm;
if (page.ViewModel?.GetType() == vm.GetType())
{
// don't replace view model if vm is null or an incompatible type.
page.ViewModel = vm;
}
else
{
this.Log().Info($"The view type '{page.GetType().FullName}' is not compatible with '{vm.GetType().FullName}' this was called by {_action}, the viewmodel was not invalidated");
}
}
}

Expand Down