gpt4 book ai didi

xamarin.forms - ReactiveTabbedPage 数据绑定(bind)

转载 作者:行者123 更新时间:2023-12-03 13:55:15 24 4
gpt4 key购买 nike

我在 Xamarin Forms 中使用 ReactiveUI 已经有一段时间了,但是在尝试使用 ReactiveTabbedPage 时遇到了障碍。我无法弄清楚 ViewModel 将如何绑定(bind)到作为 ReactiveTabbedPage 的子级的 ReactiveContentPage。

因此,作为示例,我可能有以下 XAML:

<ReactiveTabbedPage x:Name="TabbedPage">
<local:Page1View x:Name="Page1" />
<local:Page2View x:Name="Page2" />
</ReactiveTabbedPage>

其中 Page1View 和 Page2View 都是 ReactiveContentPage 类型,而 T 是关联的 ViewModel。

我期望发生的是,当 ReactiveTabbedPage 被导航到时,Page1View 将被显示,并且 ViewModel 将被加载(与我直接导航到 Page1View 的方式相同)。但是,ViewModel 永远不会被调用(构造函数永远不会被触发,也不会发生数据绑定(bind))。

但是,Page1View 和 Page2View 都会渲染,我可以看到在这些 View 中创建的初始数据(例如标签的默认文本等)。

我知道 ViewModel 的东西工作正常,因为如果我直接导​​航到 Page1View(例如不在 ReactiveTabbedPage 中),一切都会按我的预期显示。

我错过了什么,还是我走错了路?或者这只是当前版本的 RxUI 不支持?

任何意见是极大的赞赏!

最佳答案

将 VM 绑定(bind)到子页面的责任在于主机页面(即 ReactiveTabbedPage )。它只知道哪个 VM 对应于哪个 View 。

让我们一步一步来。首先,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看起来差不多。

现在我们可以开始设置 View 了。我们的 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>

请注意,它声明了每个 subview 。我们需要将 VM 连接到这些 View ,我们在 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来电。实际上,您的子虚拟机不太可能发生变化,因此直接分配它们而不是绑定(bind)是完全可以的。

现在我们的 subview 可以放在一起。这里是 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 绑定(bind),将 VM 中的属性与 UI 中的控件关联起来。再一次,您可以针对不发生变异的属性对其进行优化。

对于本示例, ChildView2ChildView1 大致相同,但显然它可能完全不同。

最终结果如您所料:

animation of reactive tabbed control

从屏幕截图中看不到但非常重要的是,当您从它切换离开时,每个选项卡都会停用(如果它实现 ISupportsActivation ,则其关联的 View 模型也会如此)。这意味着您可以在该选项卡不使用时清理该选项卡的任何绑定(bind)和订阅,从而减少内存压力并提高性能。

关于xamarin.forms - ReactiveTabbedPage 数据绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41565507/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com