2017-03-21 1 views
1

Je ne parviens pas à lier ItemClick de MvxRecyclerView (ou de son adaptateur) à une commande de mon ViewModel à l'aide de l'API Fluent. Cela fonctionne si je mets à la fois ItemsSource et ItemClick dans le XML donc je ne suis pas intéressé par une telle solution. J'ai utilisé cette publication comme un excellent guide (How to use the MvvmCross fluent API to bind a RecyclerView item's TextView to a property of its ViewModel on Android?) et tout cela fonctionne, sauf que je ne peux pas lier ItemClick sur MvxRecyclerView (ou l'adaptateur) à une commande de MainViewModel qui me mènera au fragment suivant (ItemsSource fonctionne comme un charme mais c'est une propriété et non une commande!).Liaison API MvxRecyclerView Fluent

Par souci de concision, je ne vais pas copiant le code du message original (How to use the MvvmCross fluent API to bind a RecyclerView item's TextView to a property of its ViewModel on Android?) Supposons donc que le MainViewModel de ce poste a été amélioré avec une commande ShowItemCommand en tant que tel:

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

    public MvxCommand<ViewModelItem> ShowItemCommand 
    { 
     get 
     { 
      return new MvxCommand<ViewModelItem>(selectedItem => 
      { 
       ShowViewModel<ViewModelItem> 
       (new { itemId = selectedItem.Id }); 
      }); 
     } 
    } 
} 

et tout le reste a été mis en œuvre selon le message référencé.

Donc maintenant, en plus de ItemsSource, je veux câbler ItemClick sur le MvxRecyclerView (ou l'adaptateur) à la commande. La raison pour laquelle ils sont interchangeables est que MvxRecyclerView transmet ces commandes à l'adaptateur.

Apparemment, cela devrait fonctionner ... mais il ne fonctionne pas:

adapter.ItemClick = ViewModel.ShowItemCommand; 

Cela ne fonctionne pas non plus:

set.Bind(recyclerView).For(v => v.ItemClick).To(vm => vm.ShowItemCommand); 

Répondre

0

Je ne peux pas reproduire votre problème. Je viens de créer un nouveau projet, a ajouté une RecyclerView et a ajouté la liaison suivante:

var set = this.CreateBindingSet<FirstView, FirstViewModel>(); 
set.Bind(recyclerView).For(v => v.ItemsSource).To(vm => vm.ViewModelItems); 
set.Bind(recyclerView).For(v => v.ItemClick).To(vm => vm.ShowItemCommand); 
set.Apply(); 

Cela fonctionne exactement comme prévu, où ItemClick déclenche la ShowItemCommand. Le regard de VM comme suit:

public class ViewModelItem : MvxViewModel 
{ 
    public void Init(string itemId) 
    { 
     Mvx.Trace($"Showing {itemId}"); 
    } 

    public string Id { get; set; } 
} 


public class FirstViewModel 
    : MvxViewModel 
{ 
    public FirstViewModel() 
    { 
     ViewModelItems = new ViewModelItem[] { 
      new ViewModelItem { Id = "Hello"}, 
      new ViewModelItem { Id = "World"}, 
      new ViewModelItem { Id = "Foo"}, 
      new ViewModelItem { Id = "Bar"}, 
      new ViewModelItem { Id = "Baz"} 
     }; 
    } 

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

    public MvxCommand<ViewModelItem> ShowItemCommand => 
     new MvxCommand<ViewModelItem>(DoShowItem); 

    private void DoShowItem(ViewModelItem item) 
    { 
     ShowViewModel<ViewModelItem>(new { itemId = item.Id }); 
    } 
} 
+0

Je suis d'accord avec vous. Ma mise en œuvre initiale avait seulement un MvxRecyclerView et lié à ItemsSource et ItemClick en XML. Et cela a bien fonctionné. Le remplacement de ces liaisons avec l'API Fluent fonctionne très bien. Mais je suis allé plus loin et (selon la note référencée) roulé mon propre MvxRecyclerAdapter et MvxRecyclerViewHolder. Dans cette implémentation, ItemsSource fonctionne mais ItemClick ne fonctionne pas. En fin de compte, je vise à avoir accès à MvxViewViewHolder afin d'implémenter la mise en évidence/multi-choix pour la barre d'action contextuelle. – Igor

+0

@Igor, vous devez vous assurer que vous attribuez la commande click pour votre adaptateur à votre 'ViewHolder' personnalisé, voir mon [réponse pour l'exemple de la mise en œuvre] (http://stackoverflow.com/questions/42938112/mvxrecyclerview- fluent-api-binding # answer-43055796). – Plac3Hold3r

1

Lorsque vous créez une coutume MvxRecyclerViewHolder vous devez vous assurer que vous attribuez la commande Cliquez sur la ViewHolder. Cela est effectué dans le remplacement OnCreateViewHolder de votre adaptateur personnalisé.


Exemple sur mesure 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) 
     { 
      Click = ItemClick, 
      LongClick = ItemLongClick 
     }; 
    } 
}