В моей родительской ViewModel я использую следующий код для перехода к ChildView
с использованием маршрутизации ReactiveUI
appBootstrapper.Router.Navigate.Execute(new ChildViewModel(HostScreen)).Subscribe();
Этот код работает, как и ожидалось.
Однако, когдадочернее представление закрыто, я хочу выполнить некоторые дополнительные операции (давайте использовать пример скрытия индикатора активности через свойство bool ViewModel), например
ShowActivityIndicator = true;
appBootstrapper.Router.Navigate.Execute(new ChildViewModel(HostScreen)).Subscribe();
ShowActivityIndicator = false;
Этот код не работает должным образом, потому что дочернее представлениеотображается, а затем ShowActivityIndicator = false;
выполняется немедленно.
Как переписать код так, чтобы ShowActivityIndicator = false;
выполнялся после того, как ChildView
закрыто?Спасибо!
ОБНОВЛЕНИЕ
Благодаря предложению Гленна я попытался использовать технику WhenNavigatingFromObservable().Subscribe(...)
, но лямбда-код никогда не выполняется.Мой код выглядит следующим образом ...
var microsoftSignInVM = new ViewModel.MicrosoftSignInVM(HostScreen);
//
microsoftSignInVM.WhenNavigatingFromObservable().Subscribe((_) =>
{
ShowActivityIndicator = true;
//
Data.Synchronisation.SynchroniseLocalDataCacheAsync();
//
appBootstrapper.Router.Navigate.Execute(new ViewModel.SelectJobVM(HostScreen)).Subscribe();
//
ShowActivityIndicator = false;
});
//
appBootstrapper.Router.Navigate.Execute(microsoftSignInVM).Subscribe();
Я поместил точку останова в лямбду, и она никогда не получит удар.
ОБНОВЛЕНИЕ 2 - ОБНОВЛЕНИЕ
Я создал пару минимальных тестовых классов. ЭТА РАБОТАЕТ ВЫГОДНО В ПРОЕКТЕ WPF, НО НЕ РАБОТАЕТ С ИСПОЛЬЗОВАНИЕМ ФОРМ XAMARIN ...
Shared
TestAV.xaml.cs
namespace TestApp.Test
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class TestAV : ReactiveContentPage<TestAVM>
{
public TestAV()
{
InitializeComponent();
//
this.WhenActivated(
disposables =>
{
this.BindCommand(this.ViewModel, x => x.ClickCommand, x => x.button)
.DisposeWith(disposables);
});
}
}
}
TestAVM.cs
namespace TestApp.Test
{
public class TestAVM : ReactiveObject, IEnableLogger, IRoutableViewModel
{
public TestAVM(IScreen hostScreen)
{
_HostScreen = hostScreen;
//
TestBVM testBVM = new TestBVM(_HostScreen);
//
_ClickCommand = ReactiveCommand.CreateFromObservable(() => _HostScreen.Router.Navigate.Execute(testBVM).Select(_ => Unit.Default));
//
testBVM.WhenNavigatingFromObservable().Subscribe((_) =>
{
ShowActivityIndicator = true;
});
}
//
public bool ShowActivityIndicator { get; set; }
//
private readonly ReactiveCommand<Unit, Unit> _ClickCommand; public ReactiveCommand<Unit, Unit> ClickCommand => _ClickCommand;
//
private readonly IScreen _HostScreen; public IScreen HostScreen => _HostScreen;
//
public string UrlPathSegment => "TestA";
}
}
TestBV.xaml.cs
namespace TestApp.Test
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class TestBV : ReactiveContentPage<TestBVM>
{
public TestBV()
{
InitializeComponent();
//
this.WhenActivated(
disposables =>
{
this
.BindCommand(this.ViewModel, x => x.ClickCommand, x => x.button)
.DisposeWith(disposables);
});
}
}
}
TestBVM.cs
namespace TestApp.Test
{
public class TestBVM : ReactiveObject, IEnableLogger, IRoutableViewModel
{
public TestBVM(IScreen hostScreen)
{
_HostScreen = hostScreen;
}
//
public ReactiveCommand<Unit, Unit> ClickCommand => _HostScreen.Router.NavigateBack;
//
private readonly IScreen _HostScreen; public IScreen HostScreen => _HostScreen;
//
public string UrlPathSegment => "TestB";
}
}
Специальные файлы Xamarin
AppBootstrapper.cs
namespace TestApp
{
public class AppBootstrapper : ReactiveObject, IScreen
{
public AppBootstrapper(IMutableDependencyResolver dependencyResolver = null, RoutingState router = null)
{
Router = router ?? new RoutingState();
//
RegisterParts(dependencyResolver ?? Locator.CurrentMutable);
//
Router.Navigate.Execute(new Test.TestAVM(this));
}
public RoutingState Router { get; private set; }
private void RegisterParts(IMutableDependencyResolver dependencyResolver)
{
dependencyResolver.RegisterConstant(this, typeof(IScreen));
//
dependencyResolver.Register(() => new Test.TestAV(), typeof(IViewFor<Test.TestAVM>));
dependencyResolver.Register(() => new Test.TestBV(), typeof(IViewFor<Test.TestBVM>));
}
public Page CreateMainPage()
{
return new RoutedViewHost();
}
}
}
TestAV.xaml
<?xml version="1.0" encoding="utf-8" ?>
<rxui:ReactiveContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:rxui="clr-namespace:ReactiveUI.XamForms;assembly=ReactiveUI.XamForms"
xmlns:vm="clr-namespace:TestApp.Test"
x:TypeArguments="vm:TestAVM"
x:Class="TestApp.Test.TestAV">
<ContentPage.Content>
<StackLayout>
<Button x:Name="button" Text="click A" HorizontalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage.Content>
</rxui:ReactiveContentPage>
TestBV.xaml
<?xml version="1.0" encoding="utf-8" ?>
<rxui:ReactiveContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:rxui="clr-namespace:ReactiveUI.XamForms;assembly=ReactiveUI.XamForms"
xmlns:vm="clr-namespace:TestApp.Test"
x:TypeArguments="vm:TestBVM"
x:Class="TestApp.Test.TestBV">
<ContentPage.Content>
<StackLayout>
<Button x:Name="button" Text="click B" HorizontalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage.Content>
</rxui:ReactiveContentPage>
WPF-файлы
TestAV.xaml
<rxui:ReactiveUserControl x:Class="TestApp.TestAV"
x:TypeArguments="vm:TestAVM"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:rxui="http://reactiveui.net"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:TestApp.Test">
<Grid>
<Button x:Name="button" Content="click A" />
</Grid>
</rxui:ReactiveUserControl>
TestBV.xaml
<rxui:ReactiveUserControl x:Class="TestApp.TestBV"
x:TypeArguments="vm:TestBVM"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:rxui="http://reactiveui.net"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:TestApp.Test">
<Grid>
<Button x:Name="button" Content="click B" />
</Grid>
</rxui:ReactiveUserControl>
Стоит отметить, что если я использую
_ClickCommand = ReactiveCommand.CreateFromObservable(() => _HostScreen.Router.Navigate.Execute(new TestAVM()).Select(_ => Unit.Default));
в TestBVM.cs , тогда лямбда срабатывает, как и ожидалось.
Кажется, что есть проблема с реализацией форм Xamarin Router.NavigateBack
, ноЯ открыт для других наблюдений!