Search code examples
iosxamarin.iosmvvmcross

MvxTableViewSource DequeueReusableCell issue when scrolling


We have set-up our tableviewSource and a tableview but are having issues with the data appearing in the wrong cells and select states being applied to multiple cell when scrolling a large amount of cells.

The table cells are set up according to n+1 tutorial on table cells/table views and only cause problems when part of the table is hidden due to size.

Any ideas on how to solve this?

var menuItem = item as MenuItemViewModel;

if (menuItem != null && menuItem.ViewModelType == null)
{
    NSString cellId = new NSString("Menu Header Cell");
    var headerCell = tableView.DequeueReusableCell(cellId, indexPath) as MenuItemHeaderCell;

    if (headerCell == null)
    {
        headerCell = new UITableViewCell(UITableViewCellStyle.Default, cellId) as MenuItemHeaderCell;
    }
    return headerCell;
}
else
{
    NSString cellId = new NSString("Menu Cell");
    var cell = tableView.DequeueReusableCell(cellId, indexPath) as MenuItemCell;
    if (cell == null)
    {
        cell = new UITableViewCell(UITableViewCellStyle.Default, cellId) as MenuItemCell;
    }
    return cell;
}

Following your comment I have updated the code as follows:

private static readonly NSString MenuHeaderCellIdentifier = new NSString("Menu Header Cell"); private static readonly NSString MenuItemCellIdentifier = new NSString("Menu Cell");

        public MenuTableViewSource(UITableView tableView): base(tableView)
        {
            tableView.RegisterClassForCellReuse(typeof(MenuItemHeaderCell), MenuHeaderCellIdentifier);
            tableView.RegisterClassForCellReuse(typeof(MenuItemCell), MenuItemCellIdentifier);
        }


        protected override UITableViewCell GetOrCreateCellFor(UITableView tableView, NSIndexPath indexPath, object item)
        {
            NSString cellIdentifier;

            var menuItem = item as MenuItemViewModel;
            if (menuItem.ViewModelType == null)
            {
                cellIdentifier = MenuHeaderCellIdentifier;
            }
            else
            {
                cellIdentifier = MenuItemCellIdentifier;

            }
            var cell = (UITableViewCell)TableView.DequeueReusableCell(cellIdentifier, indexPath);
            return cell;

        }

And the bindings are set up as follows:

var source = new MenuTableViewSource(TableView);
TableView.Source = source;
TableView.RowHeight = 46;

var set = this.CreateBindingSet<LeftMenuView, LeftMenuViewModel>();
set.Bind(source).To(vm => vm.MenuItems);
set.Apply();

TableView.ReloadData();

And the re-use issue is still happening. Basically if cells are off screen they start to pick up incorrect values when scrolling. Is there anything else we should be doing?


Solution

  • Thanks Stuart for your sample code. After many hours of investigating the issue I found it was only happening on iOS7 after a few more hours I realised it was down to the fact we adding a locally created variable and then delay binding to it, which seemed to result in the value going out of scope. Changing this to a member variable stopped this happening, what a long day, added to the bank of gotcha's.