¿Cómo usar la API fluida de MvvmCross para enlazar TextView de un elemento de RecyclerView a una propiedad de su ViewModel en Android?

Estoy utilizando MvvmCross en mi proyecto Xamarin Android . Tengo un MvxActivity con un MvxRecyclerView , que he asignado una plantilla del artículo en su archivo de la disposición.

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

El ViewModel es bastante simple, consiste sólo de una propiedad que contiene los datos para mostrar en el RecyclerView :

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

En general, me gusta usar el fluido MvvmCross API tanto como sea posible debido a la implícita Refactoring apoyo. Así que en mi actividad, estoy vinculando una propiedad de MvxRecyclerView como esto:

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

Hasta aquí todo bien. Ahora, el archivo de diseño para la plantilla de elemento básicamente sólo contiene un TextView :

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

Y mi clase ViewModelItem ve así:

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

Mi pregunta ahora es, ¿cómo y dónde enlazar la propiedad TextView.Text a la propiedad ViewModelItem.Title utilizando la fluida API?

Sé que es bastante fácil de hacer sin la API fluida al proporcionar un atributo MvxBind en el archivo de diseño de la plantilla de elementos, pero realmente prefiero una solución API fluida.

Heredar de MvxRecyclerAdapter y crear un adaptador personalizado para su RecyclerView. Anular OnCreateViewHolder y devolver un ViewHolder personalizado.

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

Dentro de este ViewHolder puede utilizar el Fluent API para la encuadernación.

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

En su actividad, cree el adaptador y agréguelo a su RecyclerView:

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

Y enlazar sus artículos a ItemsSource de su adaptador:

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

Sobre la base de la respuesta de Ken, he creado un par de clases de soporte y extensiones para generalizar la vinculación de los elementos y los empujó junto con una muestra de uso de github:

https://github.com/lauxjpn/MvxItemBinder

Le permite escribir enlaces de artículos como los siguientes:

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

O incluso más corto:

 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(); 
  • Personalizar RecyclerView LayoutManager no fling (sin problemas)
  • No se puede colocar la vista debajo de RecyclerView
  • Android RecyclerView crea y enlaza todas las vistas en el cambio de conjunto de datos
  • Error: no se puede encontrar la clase de símbolo RecyclerView
  • v7 RecyclerView NullPointerException AccessibilityDelegateCompat.getBridge ()
  • Desplazar RecyclerView para mostrar el elemento seleccionado en la parte superior
  • Getter no está asociado a ningún campo - Realm
  • Agregar los efectos de un RippleDrawable y un StateListDrawable a un RecyclerView
  • Recyclerview, no puedo obtener la vista del elemento con getChildAt (posición). Referencia de objeto nulo
  • ¿Cómo auto desplazarse hasta Recycler ver en Android?
  • Android setOnScrollListner en RecyclerView obsoleta
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.