Search code examples
iosxamarin.iosxamarinmvvmcross

MvxCollectionViewCell blues


I've got a UICollectionView inheriting from MvxViewController. It contains cells inheriting from MvxCollectionViewCell. The data is bound to the source through CreateBindingSet() in UICollectionView and I use DelayBind() to bind the data to the Cell when it's instantiated.

I've subclassed MvxCollectionViewSource and overridden GetOrCreateCellFor() method. Now whenever I load the data, the dequed cells retain old data.

I've considered 2 options:

  1. Create a new Cell in GetOrCreateCellFor() method. It fails because I need to pass an IntPtr in the constructor and I can't create no-arg ctor due to the contract with MvxCollectionViewCell.

  2. Update bindings when the Cell is displayed during WillDisplayCell(). This doesn't work and the old data is shown.

Any way out of this?

Edit: Added code

-- ViewWillAppear of MyView : MvxViewController

public class MyView : MvxViewController{
    // other stuff
public override void ViewWillAppear (bool animated)
    {
        var sourceOne = new MyCollectionViewSource (MyCollectionView, new NSString ("MyCollectionViewCell"));
        MyCollectionView.Source = sourceOne;
        var bindings = this.CreateBindingSet<MyView, MyViewModel> ();

        bindings.Bind (sourceOne)
                .To (vm => vm.ItemList);

        bindings.Apply ();
        MyCollectionView.ReloadData ();
    }
}

-- MyCollectionViewSource : MvxCollectionViewSource

public MyCollectionViewSource : MvxCollectionViewSource{
protected override UICollectionViewCell GetOrCreateCellFor (UICollectionView collectionView, NSIndexPath indexPath, object item)
        {
            return collectionView.DequeueReusableCell (new NSString ("MyCollectionViewCell"), indexPath) as MyCollectionViewCell;
        }
public override void WillDisplayCell (UICollectionView collectionView, UICollectionViewCell cell, NSIndexPath indexPath)
        {
            var cellz = cell as MyCollectionViewCell;
            cellz.ClearAllBindings ();
            cellz.BindUrl ();
    }
}

-- The Cell

public partial class MyCollectionViewCell : MvxCollectionViewCell {    
        public MyCollectionViewCell (IntPtr handle) : base (handle)
        {
            BindUrl();
        }
        public void BindUrl()
        {
            this.ClearAllBindings ();
            this.DelayBind(() => {
                this.CreateBinding(MyWebView)
                    .For(webView => webView.MyUrl)
                    .To<ListItemViewModel>(vm => vm.UrlEntryPoint)
                    .Apply();
          });
}

Solution

  • Ok, so I've solved this issue by mixing couple of strategies.

    1. Created a SelectedItemNo property in the DataSource

    2. In the Delegate method DecelerationEnded I calculated the current index of the cell and change the CollectionView.SelectedItemNo property to match the current visible cell.