2017-01-10 1 views
2

ReactiveUIをしばらく使用していましたが、ReactiveTabbedPageを使用しようとするとレンガの壁に当たってしまいました。私は、ViewModelがReactiveTabbedPageの子であるReactiveContentPageにどのようにバインドされるのか把握できません。ReactiveTabbedPageデータバインド

だから、一例として、私は次のXAMLを持っているかもしれません:Page1ViewとPage2ViewがタイプReactiveContentPageの両方であり、Tは、関連するViewModelにある

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

ReactiveTabbedPageがナビゲートされたときPage1Viewが表示され、ViewModelが読み込まれるということでした(私はPage1Viewに直接ナビゲートした場合と同じ方法で)。しかし、ViewModelは決して呼び出されません(コンストラクタは決して起動されず、データバインディングも発生しません)。

Page1ViewとPage2Viewの両方がレンダリングされ、これらのビューで作成された初期データ(ラベルのデフォルトテキストなど)が表示されます。

私は、ViewModelのものが正しく動作していることを知っています。私はPage1Viewに直接移動すると(ReactiveTabbedではなく)、すべてが期待どおりに表示されるからです。

私は何かを見逃してしまったのですか、それとも間違っているのでしょうか?または、現在のバージョンのRxUIではサポートされていませんか?

アドバイスをいただければ幸いです!

答えて

5

VMを子ページに割り当てる責任は、ホストページ(つまり、ReactiveTabbedPage)にあります。それだけで、どのVMがどのビューに対応しているかが分かります。

一度に1ステップずつ進んでみましょう。まず第一に、MainViewModel

public class MainViewModel : ReactiveObject 
{ 
    public ChildViewModel1 Child1 => new ChildViewModel1(); 

    public ChildViewModel2 Child2 => new ChildViewModel2(); 
} 

あなたはすべてのプロパティへのアクセス時に子供のVMを再作成したくないので、このコードは明らかに現実的ではありません。ここに関連する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のコードビハインドで行うこれらのビューにVMをフックする必要があります。

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); 
      }); 
    } 
} 

私はWhenActivatedOneWayBind呼び出しを使用して、この最も安全な方法やりました。実際には、あなたの子供のVMが変わることはまずありません。したがって、バインディングではなく直接割り当てても問題ありません。

これで、子ビューを一緒にスローすることができます。ここ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); 
      }); 
    } 
} 

は、もう一度、私たちは、UIのコントロールを持つVMのプロパティを関連付けるために良さを結合通常のRxUIをやっています。もう一度、突然変異しないプロパティに対しても最適化することができます。

この例では、ChildView2ChildView1とほとんど同じですが、明らかに完全に異なる可能性があります。あなたが期待よう

最終的な結果は次のとおりです。

animation of reactive tabbed control

何のスクリーンショットからも明らかではないのですが、非常に重要なのは、あなたが離れてから切り替えたときの各タブが非アクティブ化されていることである(それに関連するだろうとして、モデルが実装されている場合はISupportsActivation)。これは、タブが使用されていないときにそのタブのバインディングとサブスクリプションをクリーンアップすることができ、メモリの負荷を軽減し、パフォーマンスを向上させることを意味します。

+0

これはすぐには分かりませんでしたが、問題を完全に解決しました。失効についての良いニュースも! –

関連する問題