2017-03-21 28 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 
     }; 
    } 
} 
相關問題