Reputation: 316
Using Xamarin.iOS and MvvmCross, I am trying to create an MvxCollectionViewController
that contains Sections, with each Section consisting of a title and a collection of MvxCollectionViewCell
(based on the MvvmCross tutorial http://slodge.blogspot.co.uk/2013/05/n11-collectionview-n1-days-of-mvvmcross.html).
I have subclassed MvxCollectionViewCell
as set out in the tutorial. I have the following Model and ViewModel hierarchy (adapted from the tutorial):
public class Kitten
{
public string Name { get; set; }
public string ImageUrl { get; set; }
}
the ViewModel for each Section:
public class KittenSectionViewModel : MvxViewModel
{
private string _sectionName;
public string SectionName
{
get { return _sectionName; }
set { _sectionName = value; RaisePropertyChanged(() => SectionName); }
}
private List<Kitten> _kittens;
public List<Kitten> Kittens
{
get { return _kittens; }
set { _kittens = value; RaisePropertyChanged(() => Kittens); }
}
}
and then the ViewModel for all the Sections:
public class KittensViewModel: MvxViewModel
{
private readonly IKittenService _kittenService;
public List<KittenSectionViewModel> KittenSections { get; set; }
public KittensViewModel(IKittenService kittenService)
{
_kittenService = kittenService;
}
public override void Start ()
{
KittenSections = _kittenService.GetKittens().ToList();
}
}
The KittenCollectionCell
is basically unchanged:
public KittenCollectionCell (IntPtr handle) : base (handle)
{
_loader = new MvxImageViewLoader(() => MainImage);
this.DelayBind(() => {
var set = this.CreateBindingSet<KittenCollectionCell, Kitten>();
set.Bind(NameLabel).To(kitten => kitten.Name);
set.Bind (_loader).To (kitten => kitten.ImageUrl);
set.Apply();
});
}
And lastly I have implemented a custom MvxCollectionViewSource
, which I assign to the CollectionView's Source:
public class KittenCollectionViewSource : MvxCollectionViewSource
{
KittensViewModel KittensViewModel { get; set; }
public KittenCollectionViewSource (KittensViewModel kittensViewModel, UICollectionView collectionView, NSString defaultCellIdentifier) : base (collectionView, defaultCellIdentifier)
{
this.KittensViewModel = kittensViewModel;
}
public override int GetItemsCount (UICollectionView collectionView, int section)
{
return KittensViewModel.KittenSections [section].Kittens.Count;
}
public override int NumberOfSections (UICollectionView collectionView)
{
return KittensViewModel.KittenSections.Count;
}
protected override UICollectionViewCell GetOrCreateCellFor (UICollectionView collectionView, NSIndexPath indexPath, object item)
{
return collectionView.DequeueReusableCell (DefaultCellIdentifier, indexPath) as KittenCollectionCell;
}
}
(The full solution is available at https://github.com/mrtnkrstn/SectionedKittenCollectionView.git).
The problem is that the KittenCollectionCell
needs to bind to a Kitten
, but because the model is wrapped inside a different viewmodel, I don't know how to tell the MvxCollectionViewSource
to use the inner model?
Upvotes: 1
Views: 1251
Reputation: 66882
The structure of your source looks fairly simple - so I think all you are missing is the GetItemAt
override - see https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross.Binding.Touch/Views/MvxCollectionViewSource.cs#L75
I think you'll need to add something like:
protected override object GetItemAt(NSIndexPath indexPath)
{
if (KittensViewModel == null)
return null;
return KittensViewModel
.KittenSections[indexPath.Section]
.Kittens[indexPath.Row];
}
You might also be able to implement KittensViewModel
as:
protected KittensViewModel KittensViewModel { get { return base.ItemsSource as KittensViewModel; } }
Upvotes: 3