【问题标题】:MvxRecyclerView Fluent API bindingMvxRecyclerView Fluent API 绑定
【发布时间】:2017-03-21 21:05:40
【问题描述】:

我无法使用 Fluent API 将 MvxRecyclerView(或其适配器)中的 ItemClick 绑定到我的 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像魅力一样工作,但它是属性而不是命令!)。

为简洁起见,我不会复制原始帖子 (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 之外,我还想将 MvxRecyclerView(或 Adapter)上的 ItemClick 连接到命令。这些可以互换的原因是 MvxRecyclerView 只是将这些命令中继到适配器。

显然,这应该可以工作......但它没有:

adapter.ItemClick = ViewModel.ShowItemCommand;

这也不起作用:

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

【问题讨论】:

    标签: android xamarin binding xamarin.android mvvmcross


    【解决方案1】:

    创建自定义 MvxRecyclerViewHolder 时,您需要确保将 Click 命令分配给 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
            };
        }
    }
    

    【讨论】:

      【解决方案2】:

      我无法重现您的问题。我刚刚创建了一个新项目,添加了一个 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 });
          }
      }
      

      【讨论】:

      • 我同意你的看法。我最初的实现只有一个 MvxRecyclerView 并绑定到 XML 中的 ItemsSource 和 ItemClick。效果很好。用 Fluent API 替换这些绑定,效果很好。但我走得更远(根据引用的注释)推出了我自己的 MvxRecyclerAdapter 和 MvxRecyclerViewHolder。在该实现中,ItemsSource 有效,但 ItemClick 无效。最终,我的目标是访问 MvxViewViewHolder 以实现上下文操作栏的突出显示/多选。
      • @Igor,您需要确保将适配器的点击命令分配给您的自定义ViewHolder,请参阅我的answer for implementation example
      猜你喜欢
      • 2016-10-02
      • 1970-01-01
      • 1970-01-01
      • 2011-07-28
      • 1970-01-01
      • 2014-09-12
      • 2021-02-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多