2017-03-21 14 views
1

我无法使用Fluent API将ItemClick从MvxRecyclerView(或其适配器)绑定到ViewModel上的命令。如果我将两个ItemsSource和ItemClick放在XML中,它就可以工作,所以我对这样的解决方案不感兴趣。我使用这篇文章作为一个很好的指南(How to use the MvvmCross fluent API to bind a RecyclerView item's TextView to a property of its ViewModel on Android?),除了我无法绑定MvxRecyclerView(或适配器)上的ItemClick到一个MainViewModel的命令,它将带我到下一个片段(ItemsSource工程像一个魅力,但它的财产,而不是一个命令!)。MvxRecyclerView Fluent API绑定

为了简洁起见,我不会复制从原始讯息(How to use the MvvmCross fluent API to bind a RecyclerView item's TextView to a property of its ViewModel on Android?)代码,以便假定从该讯息的MainViewModel已增强的命令ShowItemCommand这样:

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

和一切都按照引用的帖子来实现。

所以,现在,除了ItemsSource之外,我想将ItemClick上的MvxRecyclerView(或适配器)连接到该命令。这些可互换的原因是MvxRecyclerView只是将这些命令转发给适配器。

显然,这应该工作...但事实并非如此:

adapter.ItemClick = ViewModel.ShowItemCommand; 

这不起作用或者:

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

回答

0

我无法重现您的问题。我刚刚创建了一个新的项目,增加了RecyclerView并添加以下绑定:

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

这个工程只是预期,其中ItemClick触发ShowItemCommand。虚拟机的外观如下:

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

我同意你的看法例。我最初的实现只有一个MvxRecyclerView,并绑定到XML中的ItemsSource和ItemClick。这很好。用Fluent API替换这些绑定,效果很好。但我走得更远了(按照引用的注释)推出了我自己的MvxRecyclerAdapter和MvxRecyclerViewHolder。在那个实现中,ItemsSource起作用,但ItemClick不起作用。最终,我打算访问MvxViewViewHolder以实现上下文操作栏的突出显示/多项选择。 – Igor

+0

@Igor,您需要确保您将适配器的click命令分配给您的自定义'ViewHolder',请参阅我的[实现示例的答案](http://stackoverflow.com/questions/42938112/mvxrecyclerview-流畅的API结合#答案-43055796)。 – Plac3Hold3r

1

在创建自定义MvxRecyclerViewHolder你需要确保你在分配点击命令到ViewHolder。这是在您的自定义适配器的覆盖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) 
     { 
      Click = ItemClick, 
      LongClick = ItemLongClick 
     }; 
    } 
} 
相关问题