2016-06-17 10 views
5

私はアクティビティから別のアクティビティに移動しようとしています。私はまだMVVMCrossについて学んでいますので、この全体のパターンはまだ私にとって非常に新しいものです。私はXamarin.Androidでそれを適用している瞬間です。MVVMCross:Xamarin.AndroidイベントをViewModelコマンドにバインドする方法

セットアップ:

  1. MainDashboardActivityは、AndroidデザインサポートライブラリのNavigationView.

  2. のViewModel MainDashboardViewModelが別のアクティビティへの単純なShowViewModelあるIMvxCommand GoToSecondDashboardを持っています。

NavigationViewにはNavigationItemSelectedイベントがあります。

navigationView.NavigationItemSelected += (o, e) => 
{ 
    if(e.MenuItem.ItemId == Resource.Id.SecondDashboardMenu) 
    { 
     // make new intent to target activity 
    } 
}; 

は、今私はViewModelにのIMvxCommandにナビゲーションロジックを押し込めなかった、と私はNavigationViewのイベントにバインドしたい、もはや意図やその他もろもろを作成:通常は、私はこれを行うだろう。どうすればこれを達成できますか?

私はthis answerがないかのように、レイアウトのコードファイルとないで流暢なバインディングロジックを使用したい:

protected override void OnViewModelSet() 
{ 
    SetContentView(Resource.Layout.View_Tip); 

    var edit = this.FindViewById<EditText>(Resource.Id.FluentEdit); 

    var set = this.CreateBindingSet<TipView, TipViewModel>(); 
    set.Bind(edit).To(vm => vm.SubTotal); 
    set.Apply(); 

    // for non-default properties use 'For': 
    // set.Bind(edit).For(ed => ed.Text).To(vm => vm.SubTotal); 

    // you can also use: 
    // .WithConversion("converter", "optional parameter") 
    // .OneTime(), .OneWay() or .TwoWay() 
} 

しかしNavigationItemSelectedはイベントです。イベントにコマンドをバインドする方法を見つけることができませんでした。それが起こる前にItemIdをフィルタリングするロジックもありますので、簡単なイベント・ツー・コマンド・バインディングではありません。

これが正しい方法であるかどうかはわかりません。私が望むのは、レイアウトファイルではなくメニュータップをコードファイルのコマンドにバインドすることだけです。

+0

レイアウトファイルでバインディングを実行しないでください。私の意見では、通常のアプローチは次のようになります。 1.メニュー項目のモデルを定義します。 2.メニュー項目のビューモデルにリストを定義します。 3.メニュー項目のレイアウトを定義します。 4.メニュー項目をレイアウト上のNavigationViewにバインドします。 5.メニュー項目のレイアウトをナビゲーションビューに設定します。 6.メニュー項目の種類を想定したコマンドを定義します。 7. NavigationViewにコマンドをバインドします。 レイアウト上でやりたいと思っていないのであれば、私がコード内で行った部分が見つかるかどうかわかります。 – Cyriac

+0

私は(制限された)経験はAndroidを直接扱うことから来ており、コードからバインドする傾向があるため、コード自体の中からバインドすることに慣れています。そして、コードを使ってレイアウトを混乱させることは、私にとってはちょっとエイリアンに感じるので、それがあります。 私がNavigationViewについて知っていることは、ヘッダーのレイアウトとメニュー項目(レイアウトではない)のメニュー.xmlが付属していることです。そのようなプロセスのサンプルはありますか? – batrand

+0

私は、後でその事例を投稿することができますか、すでにそれを実装していた同僚に尋ねることができます。ちょっとエイリアンを感じるかもしれませんが、慣れていれば本当に快適です。特別な状況ではコードバインディングのみを使用しています。両方とも正と負の側面があります。 – Cyriac

答えて

6

NavigationViewにバインドターゲットが定義されていないため、Cyriac describes in his postとしてバインドすることはできません。

内部的にターゲットバインディングとは、単にイベントを購読してそれに反応し、そのデータをプロパティとして公開することです。

だから、現在NavigationViewItemsSourceとバインドを取る方法がないので、あなたがeventまでEventHandlerをフック、すでに行っているような何かをし、あなたのViewModelに直接呼び出す必要があり、すなわち呼び出しますコマンド。

navigationView.NavigationItemSelected += ItemSelected; 

private void ItemSelected(object sender, NavigationItemSelectedEventArgs args) 
{ 
    ViewModel.NavigateCommand.Execute(args.MenuItem.TitleFormatted.ToString()); 
} 

その後、あなたのCommandであなたのViewModel中:

private void DoNavigateCommand(string title) 
{ 
    if (title == "Derp") 
     ShowViewModel<DerpViewModel>(); 
} 

代わりにあなたがバインディングターゲットにこのコードをラップすることができこれは次のようになります。これらがどのように実装されているかを見ることができますin the official MvvmCross github repository

+0

ああ、ちょっと、バインディングが追加されたと想像してください。知っておいてよかった!タイ! – Cyriac

+0

恐ろしい!私が望んでいたように聞こえました。私は月曜日に確認します! – batrand

+0

さて、動作していますが、コードとは少し異なります。 ViewModelは '(ViewModel as MainDashboardViewModel).NavigateToViewModel(" second ")Execute();' ViewModelでは、 'NavigateToViewModel'は実行するアクティビティのコマンドを返す単純な関数です。どのようにして、アクティビティが直接コマンドを実行できるようにViewModelを設定しますか? – batrand

2

私はhttp://crosscuttingconcerns.com/MvvmCross-Fluent-Databindingで他の人の回答を見つけました。これは試してみるべきです。私はあなたがちょうど直接イベントを参照することができないと思う、むしろ文字列を使用する必要があります。

protected override void OnViewModelSet() 
{ 
     SetContentView (Resource.Layout.TermsPage); 

     var set = this.CreateBindingSet<TermsView, TermsViewModel>(); 
     set.Bind(FindViewById<Button>(Resource.Id.acceptTermsButton)) 
      .For("Click") 
      .To(vm => vm.AcceptTermsCommand); 
     set.Apply(); 
} 

もちろん、イベントに応じて調整する必要があります。

+0

私は仕事を辞めましたので、今はテストできません...月曜日に更新されます! – batrand

関連する問題