0
votes

I'm new to MVVMCross, theoretically it's shouldn't be that hard until I started using UICollectionViewCell

I have multiple sections in my view controller, and each of them should bind to different types of data, what should I do?

in the ViewModel, it has a list and a property I want to use the following properties to fill my custom cells

List<ClassForCell1> list;
private int _valueForCell2;

public int ValueForCell2
{
    get => _valueForCell2;
    set => _valueForCell2 = value;
}

In MySource class, I registered different types of Cell, which looks like this

public MySource(UICollectionView collectionView, ViewModel viewModel) : base(collectionView)
{
    _viewModel = viewModel;
    collectionView.RegisterClassForCell(typeof(CustomCell1), CustomCell1.Key);
    collectionView.RegisterNibForCell(CustomCell2.Nib, CustomCell2.Key);
    //... some other cell registration
}

Here are my Cells

protected CustomCell1(IntPtr handle) : base(handle)
{
    this.DelayBind(() =>
    {
        var set = this.CreateBindingSet<CustomCell1, ClassForCell1>();
        set.Bind(NameLabel).To(m => m.name);
        set.Apply();
    });
}

protected CustomCell2(IntPtr handle) : base(handle)
{
    this.DelayBind(() =>
    {
        // how to bind this one?
        var set = this.CreateBindingSet<CustomCell2, ???>();
        set.Bind(NameLabel).To(a view model's value); // ValueForCell2 in ViewModel
        set.Apply();
    });
}

My questions are:

  1. How can I bind viewModel's specific property or list to the specific cell(s) or section(s)?

here's the code snippet in my ViewController, in order to bind ViewController and ViewModel, and it seems like doesn't work at all

var source = new MySource(MyCollectionView, MyViewModel);
var set = this.CreateBindingSet<MyViewController, MyViewModel>();
  1. For CustomCell2, how to bind a label's Text property to view model's property? (ValueForCell2)
1

1 Answers

1
votes

There needs to be separate ViewModels for each of the cells as well as your parent ViewModel that exposes the List of items you want to display.

Since you want two different types of cells to show up, you need a common base class to describe them. To achieve that, you can create a BaseCellViewModel class as such:

public abstract class BaseCellViewModel : MvxViewModel
{
    private string _name;
    public string Name {
        get { return _name; }
        set { SetProperty(ref _name, value); }
    }
}

Now that you have a base class setup, you can create ViewModels for each of the cells you want to display:

public class FirstCustomCellViewModel : BaseCellViewModel
{
  //add any properties that are specific to the first type of cell
}

public class SecondCustomCellViewModel : BaseCellViewModel
{
  //add any properties that are specific to the second type of cell
}

Now that all the ViewModels for the cells are setup, you can setup your parent ViewModel like this:

public class ListViewModel : MvxViewModel
{
    private ObservableCollection<BaseCellViewModel> _listItems { get; set; }
    public virtual ObservableCollection<BaseCellViewModel> ListItems {
        get { return _listItems; }
        set { _listItems = value; 
            RaisePropertyChanged(() => ListItems);
        }
    }
}

Notice that the collection is constrained to the BaseCellViewModel type. This allows you to add both FirstCustomCellViewModel and SecondCustomCellViewModel objects into it:

ListItems = new ObservableCollection<CellViewModelBase>(){
    new FirstCustomCellViewModel(),
    new SecondCustomCellViewModel()
};

Now you define the bindings in your cells like this:

protected CustomCell1(IntPtr handle) : base(handle)
{
    this.DelayBind(() =>
    {
        var set = this.CreateBindingSet<CustomCell1, FirstCustomCellViewModel>();
        set.Bind(NameLabel).To(vm => vm.Name);
        set.Apply();
    });
}

protected CustomCell2(IntPtr handle) : base(handle)
{
    this.DelayBind(() =>
    {
        var set = this.CreateBindingSet<CustomCell2, SecondCustomCellViewModel>();
        set.Bind(NameLabel).To(vm => vm.Name); 
        set.Apply();
    });
}

And in your ViewController that has the UICollectionView, you just bind the source:

var source = new MyCollectionViewSource(MyCollectionView, MyViewModel);
var set = this.CreateBindingSet<MyViewController, ListViewModel>();
set.Bind(source).To(vm => vm.ListItems);
set.Apply();