5

私はMvvmCross私のXamarin Androidプロジェクトで使用しています。私はMvxRecyclerViewMvxActivityを持っています。レイアウトファイルにアイテムテンプレートを割り当てました。MvvmCross Fluent APIを使用して、RecyclerViewアイテムのTextViewをAndroid上のViewModelのプロパティにバインドする方法はありますか?

public class MainViewModel : MvxViewModel 
{ 
    private IEnumerable<ViewModelItem> _viewModelItems; 
    public IEnumerable<ViewModelItem> ViewModelItems 
    { 
     get { return _viewModelItems; } 
     set { SetProperty(ref _viewModelItems, value); } 
    }  
} 

は、一般的に、私はMvvmCross流暢APIを使用するため、可能な限り好き:

<MvxRecyclerView 
    android:id="@+id/my_recycler_view" 
    local:MvxItemTemplate="@layout/item_recycler_view" /> 

のViewModelはそれだけでRecyclerViewに表示するデータを保持している一つの特性で構成され、非常に簡単です暗黙のリファクタリングサポートの だから私の活動で、私はこのようなMvxRecyclerViewのプロパティをバインドしています。これまでのところ

var recyclerView = View.FindViewById<MvxRecyclerView>(Resource.Id.my_recycler_view); 
var set = this.CreateBindingSet<MainView, MainViewModel>(); 
set.Bind(recyclerView) 
    .For(v => v.ItemsSource) 
    .To(vm => vm.ViewModelItems); 
set.Apply(); 

とても良いです。

<LinearLayout> 
    <TextView 
     android:id="@+id/innerText" /> 
</LinearLayout> 

そして、私のViewModelItemクラスには、次のようになります:さて、項目テンプレートのレイアウトファイルは、基本的にはTextViewが含まれてい

public class ViewModelItem 
{ 
    public string Title { get; set; } 
} 

私の質問今、どこでどのように私はTextView.TextをバインドしますFluent APIを使用してプロパティのViewModelItem.Titleプロパティにアクセスしますか?

MvxBind属性をアイテムテンプレートレイアウトファイルに指定すると、流暢なAPIがなくても非常に簡単ですが、私は実際には流暢なAPIソリューションを好むでしょう。

答えて

10

MvxRecyclerAdapterから継承し、RecyclerViewのカスタムアダプタを作成します。 OnCreateViewHolderをオーバーライドし、カスタムViewHolderを返します。

public class MyAdapter : MvxRecyclerAdapter 
{ 
    public MyAdapter(IMvxAndroidBindingContext bindingContext) 
     : base(bindingContext) 
    { 
    } 

    public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType) 
    { 
     var itemBindingContext = new MvxAndroidBindingContext(parent.Context, this.BindingContext.LayoutInflaterHolder); 
     var view = this.InflateViewForHolder(parent, viewType, itemBindingContext); 

     return new MyViewHolder(view, itemBindingContext); 
    } 
} 

このViewHolder内では、Fluent APIをバインディングに使用できます。あなたの活動に

public class MyViewHolder : MvxRecyclerViewHolder 
{ 
    private readonly TextView textView; 

    public MyViewHolder(View itemView, IMvxAndroidBindingContext context) 
     : base(itemView, context) 
    { 
     this.textView = itemView.FindViewById<TextView>(Android.Resource.Id.Text1); 

     this.DelayBind(() => 
     { 
      var set = this.CreateBindingSet<MyViewHolder, ViewModelItem>(); 
      set.Bind(this.textView).To(x => x.Title); 
      set.Apply(); 
     }); 
    } 
} 

アダプタを作成し、あなたのRecyclerViewに追加:

var adapter = new MyAdapter((IMvxAndroidBindingContext)this.BindingContext); 
recyclerView.Adapter = adapter; 

とあなたのアダプタののItemsSourceにあなたのアイテムをバインド:ケンの回答に基づいて

set.Bind(this.adapter).For(x => x.ItemsSource).To(x => x.ViewModelItems); 
+1

一つのことを、あなたは、クリックコマンドを経由割り当てることができますカスタム 'ViewHolder'に、そうでなければItemClickへのバインディングは何の影響も与えません。[this stackoverflow answer]の例(http://stackoverflow.com/questions/42938112/mvxrecyclerview-fluent-api-binding#answer-43055796)。 – Plac3Hold3r

2

、私はアイテムのバインディングを一般化するためにいくつかのサポートクラスと拡張を作成し、githubへの使用サンプルと共にそれらをプッシュしました:

https://github.com/lauxjpn/MvxItemBinder

それはあなたが以下のような項目バインディング記述することができます:

var recyclerView = FindViewById<MvxRecyclerView>(Resource.Id.RecyclerView); 

var set = this.CreateBindingSet<MainActivity, MainViewModel>(); 
set.Bind(recyclerView) 
    .For(v => v.ItemsSource) 
    .To(vm => vm.Items); 
set.Apply(); 

recyclerView.BindItems<ItemViewModel>(this, (itemView, itemSet) => 
    itemSet.Bind(itemView.FindViewById<TextView>(Resource.Id.item_template)) 
     .For(v => v.Text) 
     .To(vm => vm.Title) 
); 

あるいは短い:注意すべき

var recyclerView = FindViewById<MvxRecyclerView>(Resource.Id.RecyclerView); 

var set = this.CreateBindingSet<MainActivity, MainViewModel>(); 
set.Bind(recyclerView.BindItems<ItemViewModel>(this, (itemView, itemSet) => 
     itemSet.Bind(itemView.FindViewById<TextView>(Resource.Id.item_template)) 
      .For(v => v.Text) 
      .To(vm => vm.Title))) 
    .For(v => v.ItemsSource) 
    .To(vm => vm.Items); 
set.Apply(); 
関連する問題