如何使用MvxRecyclerView在MvvmCross中实现Recycler View

时间:2017-01-09 20:22:29

标签: xamarin data-binding xamarin.android mvvmcross

在MvvmCross中,我在一个有效的活动中有一个android listview。

我在某处读到将listView更改为recyclerView就像在我的布局.axml文件中将MvxListView更改为MvxRecyclerView一样简单。尝试这会给我以下运行时异常:

Android.Views.InflateException: Binary XML file line #1: Binary XML file line #1: Error inflating class Mvx.MvxRecyclerView

使用MvxRecyclerView时,在代码隐藏或视图模型中是否还有其他不同之处?以下是我的代码。

布局文件:

Main.axml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Mvx.MvxRecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical"
        android:id="@+id/words_listview"
        local:MvxItemTemplate="@layout/words_listview_row"
        local:MvxBind="ItemsSource Words" />
</LinearLayout> 

words_listview_row.axml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:p1="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    p1:minWidth="25px"
    p1:minHeight="25px"
    p1:layout_width="match_parent"
    p1:layout_height="match_parent"
    p1:id="@+id/relativeLayout1"
    p1:background="#FFFFFF">
    <TextView
        p1:text="Word name"
        p1:layout_width="wrap_content"
        p1:layout_height="wrap_content"
        p1:id="@+id/headingTextView"
        p1:width="325dp"
        p1:textColor="#000000"
        p1:layout_alignParentLeft="true"
        p1:textSize="18sp"
        p1:paddingLeft="20dp"
        p1:paddingTop="15dp"
        local:MvxBind="Text Name" />
    <TextView
        p1:text="Word meaning"
        p1:layout_width="match_parent"
        p1:layout_height="wrap_content"
        p1:layout_below="@id/headingTextView"
        p1:id="@+id/detailTextView"
        p1:textColor="#8f949a"
        p1:layout_alignParentLeft="true"
        p1:textSize="16sp"
        p1:paddingLeft="20dp"
        p1:paddingRight="20dp"
        p1:paddingBottom="15dp"
        local:MvxBind="Text Meaning" />
</RelativeLayout>

WordViewModel.cs

using MvvmCross.Core.ViewModels;
using VocabBuilder.Core.Models;
using VocabBuilder.Core.Services.Interfaces;

namespace VocabBuilder.Core.ViewModels
{
    public class WordViewModel : MvxViewModel
    {
        private IWordService _wordService;

        public MvxObservableCollection<Word> Words { get; set; }

        public WordViewModel(IWordService wordService)
        {
            Words = new MvxObservableCollection<Word>();

            _wordService = wordService;

            Words.ReplaceWith(_wordService.GetAllWords());
        }
    }
}

Codebehind / WordView.cs

using Android.App;
using Android.OS;
using MvvmCross.Droid.Views;
using VocabBuilder.Core.ViewModels;

namespace VocabBuilder.UI.Droid.Views
{
    [Activity(Label="Vocab Builder", MainLauncher=true)]
    public class WordView : MvxActivity<WordViewModel>
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            SetContentView(Resource.Layout.Main);
        }
    }
}

感谢。

编辑:

这是我的Setup.cs文件:

using Android.Content;
using MvvmCross.Core.ViewModels;
using MvvmCross.Droid.Platform;

namespace VocabBuilder.UI.Droid
{
    public class Setup : MvxAndroidSetup
    {
        public Setup(Context applicationContext) : base(applicationContext)
        {
        }

        protected override IMvxApplication CreateApp()
        {
            return new Core.App();
        }
    }
}

1 个答案:

答案 0 :(得分:4)

好吧,在用MvxRecyclerView替换MvxListView后,我可以轻松地使用RecyclerView。不确定你的实现的具体问题是什么,但我会给你我的花絮,你可以尝试全部。

我的RecyclerView存在于继承自MvxFragment的Fragment中 - 与您的有点不同,但不应该是决定因素。以下是一些Fragment片段:

public class ListsFragment : MvxFragment<ListsViewModel>
{
   ...
   public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
   {
      base.OnCreateView(inflater, container, savedInstanceState);
      var view =  this.BindingInflate(Resource.Layout.fragment_listsfragment, null);   
      return view;
   }
   ...
}

这是fragment_listsfragment的axml:

<?xml version="1.0" encoding="utf-8"?>
<MvvmCross.Droid.Support.V7.RecyclerView.MvxRecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    app:MvxItemTemplate="@layout/item_list"
    app:MvxBind="ItemsSource Lists; ItemClick ShowListItemsCommand" />

我确实看到你的ViewModel实现有点不同 - 我的是这样的:

public class ListsViewModel : BaseViewModel
{
  ...
  private readonly IListService _listService;
  private ObservableCollection<Models.List> _lists;

  public ObservableCollection<Models.List> Lists
  {
    get { return _lists; }
    set
    {
      _lists = value;
      RaisePropertyChanged(() => Lists);
    }
  }

  public MvxCommand<Models.List> ShowListItemsCommand
  {
    get
    {
      return new MvxCommand<Models.List>(selectedList =>
      {
        ShowViewModel<ListItemsViewModel>
                (new { listId = selectedList.Id });
      });
    }
  }
  ...
  public override async void Start()
  {
    base.Start();
    await InitializeAsync();
  }

  protected override async Task InitializeAsync()
  {
    await _listService.InitializeAsync();
    Lists = (await _listService.GetListsAsync())
            .ToObservableCollection();
  }
}

希望这有帮助。