Ответственность за привязку виртуальной машины к дочерним страницам лежит на главной странице (то есть ReactiveTabbedPage
). Он сам знает, какая виртуальная машина соответствует какому виду.
Давайте сделаем это шаг за шагом. Прежде всего, MainViewModel
:
public class MainViewModel : ReactiveObject
{
public ChildViewModel1 Child1 => new ChildViewModel1();
public ChildViewModel2 Child2 => new ChildViewModel2();
}
Этот код, очевидно, не является реалистичным, потому что вы не хотели бы, чтобы воссоздать ребенка виртуальных машин на каждом доступе к собственности. Это больше API, который здесь уместен.
ChildViewModel1
выглядит следующим образом:
public class ChildViewModel1 : ReactiveObject
{
public string Test => "Hello";
}
И ChildViewModel2
выглядит так же.
Теперь мы можем настроить настройку. Наша MainView.xaml
выглядит следующим образом:
<?xml version="1.0" encoding="utf-8" ?>
<rxui:ReactiveTabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:TypeArguments="vms:MainViewModel"
xmlns:local="clr-namespace:ReactiveTabbedPageTest"
xmlns:rxui="clr-namespace:ReactiveUI.XamForms;assembly=ReactiveUI.XamForms"
xmlns:vms="clr-namespace:ReactiveTabbedPageTest.VMs"
x:Class="ReactiveTabbedPageTest.MainView">
<local:Child1View x:Name="child1View" Title="Child 1"/>
<local:Child2View x:Name="child2View" Title="Child 2"/>
</rxui:ReactiveTabbedPage>
Обратите внимание, что говорит каждый из представлений детей. Нам нужно подключить виртуальные машины к этим мнениям, которые мы делаем в отделенном коде для MainView
:
public partial class MainView : ReactiveTabbedPage<VMs.MainViewModel>
{
public MainView()
{
InitializeComponent();
this.ViewModel = new VMs.MainViewModel();
this.WhenActivated(
disposables =>
{
this
.OneWayBind(this.ViewModel, x => x.Child1, x => x.child1View.ViewModel)
.DisposeWith(disposables);
this
.OneWayBind(this.ViewModel, x => x.Child2, x => x.child2View.ViewModel)
.DisposeWith(disposables);
});
}
}
Я сделал это самым безопасным способом с помощью WhenActivated
и OneWayBind
вызовов. На самом деле, маловероятно, что ваши дочерние виртуальные машины изменятся, поэтому прямое назначение их, а не привязка, будет полностью прекрасным.
Теперь наши детские взгляды могут быть брошены вместе.Вот ChildView1.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"
x:Class="ReactiveTabbedPageTest.Child1View"
x:TypeArguments="vms:ChildViewModel1"
xmlns:rxui="clr-namespace:ReactiveUI.XamForms;assembly=ReactiveUI.XamForms"
xmlns:vms="clr-namespace:ReactiveTabbedPageTest.VMs">
<Label x:Name="label" VerticalTextAlignment="Center" HorizontalTextAlignment="Center"/>
</rxui:ReactiveContentPage>
И фоновый код:
public partial class Child1View : ReactiveContentPage<ChildViewModel1>
{
public Child1View()
{
InitializeComponent();
this.WhenActivated(
disposables =>
{
this
.OneWayBind(this.ViewModel, x => x.Test, x => x.label.Text)
.DisposeWith(disposables);
});
}
}
Еще раз мы делаем обычный RxUI обязательной благости связать свойства в VM с элементами управления в пользовательском интерфейсе. И еще раз вы можете оптимизировать это для свойств, которые не мутируют.
Для целей настоящего примера ChildView2
- это то же самое, что и ChildView1
, но, очевидно, это может быть совершенно иначе.
Конечный результат, как и следовало ожидать:
Что не видно из скриншота, но очень важно, что каждая вкладка деактивируется при переходе от него (как бы связанный с ним просмотреть модель, если она реализована ISupportsActivation
). Это означает, что вы можете очистить любые привязки и подписки для этой вкладки, когда она не используется, уменьшая давление памяти и улучшая производительность.
Это было не сразу очевидно, но прекрасно решает проблему! Хорошие новости о деактивации тоже! –