Unable to bind to ios table section cells in mvvmc

2019-04-13 05:00发布

问题:

I'm trying to create a TableView with grouped sections like so:

I am binding a list of groups to the table. A group contains a few string properties and a list of items, while an item contains some string properties as well. The group and item cells each have their own class which extends MvxTableViewCell.

Inside the class for each the cells I am binding as follows:

The item cell:

 this.DelayBind(() =>
                {
                    var set = this.CreateBindingSet<ItemCellView, ItemCellViewModel>();
                    set.Bind(lblOne).To(item=> item.propertyOne);
                    set.Apply();
                });

And the group cell:

this.DelayBind(() =>
                    {
                        var set = this.CreateBindingSet<GroupCellView, GroupCellViewModel>();
                        set.Bind(lblOne).To(group=> group.propertyOne);
                        set.Apply();
                    });

My TableSource in the main view extends MvxStandardTableViewSource and uses the overridden methods to get the respective cells for the table. public override UIView GetViewForHeader returns a group cell view while protected override UITableViewCell GetOrCreateCellFor returns an item cell view.

My problem is that the group view cell does not bind whatsoever while the item view cell binds just fine even though I see no discernible difference between the two. The group view cell is being constructed however, it's just the binding that is not taking place inside the cell.

Edit: Added the table view source:

private class TableSource : MvxStandardTableViewSource
        {
            private List<GroupCellViewModel> _groups;
            public new List<GroupCellViewModel> ItemsSource
            {
                get
                {
                    return _groups;
                }
                set
                {
                    _groups = value;
                    ReloadTableData();
                }
            }

            public TableSource(UITableView tableView)
                : base(tableView)
            {
            }

            public override string TitleForHeader(UITableView tableView, int group)
            {
                if (_groups == null)
                    return string.Empty;

                return Utils.FormatDate(_groups[group].Date);
            }

            public override UIView GetViewForHeader(UITableView tableView, int group)
            {
                return MakeHeaderRow(tableView, _groups[group]);
            }

            public override float GetHeightForHeader(UITableView tableView, int section)
            {
                return 50;
            }

            public override float GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
            {
                return 50;
            }

            public override int NumberOfSections(UITableView tableView)
            {
                if (_groups == null)
                    return 0;

                return _groups.Count;
            }

            public override int RowsInSection(UITableView tableview, int group)
            {
                if (_groups == null)
                    return 0;

                return _groups[group].Items.Count;
            }

            protected override UITableViewCell GetOrCreateCellFor(UITableView tableView, NSIndexPath indexPath, object item)
            {
                UITableViewCell cell;
                if (item is Item)
                {
                    cell = MakeItemRow(tableView, (Item)item);
                }
                else
                {
                    throw new ArgumentException("Unknown cell type " + item.GetType().Name);
                }

                return cell;
            }

            protected override object GetItemAt(NSIndexPath indexPath)
            {
                if (_groups == null)
                    return null;

                return _groups[indexPath.Section].Items[indexPath.Row];
            }

            private UITableViewCell MakeHeaderRow(UITableView tableView, GroupCellViewModel group)
            {
                var existing = (GroupCellView)tableView.DequeueReusableCell(GroupCellView.Key);
                if (existing != null)
                    return existing;

                return new GroupCellView();
            }

            private UITableViewCell MakeItemRow(UITableView tableView, Item item)
            {
                var existing = (ItemCellView)tableView.DequeueReusableCell(ItemCellView.Key);
                if (existing != null)
                    return existing;

                return new ItemCellView();
            }
        }

回答1:

I think your solution is almost there - but you'll need to provide a GetViewForHeader implementation which is a bit more like the binding GetCell implementation which MvvmCross provides - note the DataContext setting in:

    public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
    {
        var item = GetItemAt(indexPath);
        var cell = GetOrCreateCellFor(tableView, indexPath, item);

        var bindable = cell as IMvxDataConsumer;
        if (bindable != null)
            bindable.DataContext = item;

        return cell;
    }

from https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross.Binding.Touch/Views/MvxBaseTableViewSource.cs#L97

For the header, you'll need to set the DataContext to the appropriate "view model" for the group header.