Tengo dos celdas con diferentes alturas. Cuando elimino el primero, el segundo obtiene la altura del primero

Algún context

En esta pantalla puede agregar y eliminar personas. No todos los campos son necesarios, por lo que la altura de la celda es dinámica.

El problema

Si añado primero a una persona con todos los campos completados, luego a una segunda persona que no completó todos los campos, y luego elimino a la primera persona, la segunda ocupa el primer lugar, pero con el layout de la primera persona

IMPORTANTE

Después de eliminar a la primera persona, si me desploop hasta que la celda restante esté fuera de la pantalla, se corrige a sí misma

Código

Esta es la fuente de la tabla

namespace xXxx.xXxx.iOS { public class SiniestroParticipantesSource : MvxTableViewSource { private readonly SiniestroParticipantesViewModel viewModel; public SiniestroParticipantesSource(UITableView tableView, SiniestroParticipantesViewModel viewModel) : base(tableView) { this.UseAnimations = true; this.AddAnimation = UITableViewRowAnimation.Top; this.RemoveAnimation = UITableViewRowAnimation.Middle; this.viewModel = viewModel; tableView.RegisterNibForCellReuse(UINib.FromName(PersonaDenunciaCellView.Key, NSBundle.MainBundle), PersonaDenunciaCellView.Key); } public override void RowSelected(UITableView tableView, NSIndexPath indexPath) { tableView.DeselectRow(indexPath, true); var itemPersona = this.viewModel.Personas[indexPath.Section]; this.viewModel.AgregarCommand.Execute(itemPersona); } protected override UITableViewCell GetOrCreateCellFor(UITableView tableView, NSIndexPath indexPath, object item) { var cell = (PersonaDenunciaCellView)tableView.DequeueReusableCell(PersonaDenunciaCellView.Key, indexPath); return cell; } public override nint RowsInSection(UITableView tableview, nint section) { return 1; } public override nint NumberOfSections(UITableView tableView) { return this.viewModel.Personas.Count; } protected override object GetItemAt(NSIndexPath indexPath) { return this.viewModel.Personas[indexPath.Section]; } } } 

Esta es la vista de celda

 namespace xXxx.xXxx.iOS { public partial class PersonaDenunciaCellView : MvxTableViewCell { public static readonly NSString Key = new NSString("PersonaDenunciaCellView"); public static readonly UINib Nib; static PersonaDenunciaCellView() { Nib = UINib.FromName("PersonaDenunciaCellView", NSBundle.MainBundle); } protected PersonaDenunciaCellView(IntPtr handle) : base(handle) { this.DelayBind(() => { var set = this.CreateBindingSet<PersonaDenunciaCellView, PersonaDenunciaItemViewModel>(); set.Bind(btnRemove).To(vm => vm.RemoveCommand); set.Bind(lblNombre).To(vm => vm.Persona.Persona.Nombre); set.Bind(lblTipoDoc).To(vm => vm.Persona.Persona.TipoDoc.Descripcion); set.Bind(tipoDocVisibilityConst).For("Priority").To(vm => vm.Persona.Persona.Nrodoc).WithConversion("iOSVisibility", true); set.Bind(lblNrodoc).To(vm => vm.Persona.Persona.Nrodoc); set.Bind(nroDocVisibilityConst).For("Priority").To(vm => vm.Persona.Persona.Nrodoc).WithConversion("iOSVisibility", true); set.Bind(lblMailContacto).To(vm => vm.Persona.MailContacto); set.Bind(mailContactoVisibilityConst).For("Priority").To(vm => vm.Persona.MailContacto).WithConversion("iOSVisibility", true); set.Bind(lblTelContacto).To(vm => vm.Persona.TelContacto); set.Bind(telContactoVisibilityConst).For("Priority").To(vm => vm.Persona.TelContacto).WithConversion("iOSVisibility", true); set.Bind(lblLesionado).To(vm => vm.Persona.Lesionado).WithConversion("Lesionado"); set.Bind(vehiculoVisibilityConst).For("Priority").To(vm => vm.Persona.Patente).WithConversion("iOSVisibility", true); set.Bind(viewVehiculo).For("Visibility").To(vm => vm.Persona.Patente).WithConversion("Visibility"); set.Bind(lblPatente).To(vm => vm.Persona.Patente); set.Bind(lblCiaSeguroDesc).To(vm => vm.Persona.CiaSeguroDesc); set.Apply(); }); } } } 

Cell ViewModel

 namespace xXxx.xXxx.Core.ViewModels.Items { public class PersonaDenunciaItemViewModel:MvxViewModel { private readonly IMvxMessenger messenger; private readonly IUserInteraction userInteraction; public string Index { get; set; } public PersonaDenunciaItemViewModel (SiniestroCarga.PersonaDenuncia persona, IMvxMessenger messenger, IUserInteraction userInteraction, string index) { this.messenger = messenger; this.userInteraction = userInteraction; this.Persona = persona; this.Index = index; } private SiniestroCarga.PersonaDenuncia persona; public SiniestroCarga.PersonaDenuncia Persona { get { return this.persona; } set { this.persona = value; this.RaisePropertyChanged(() => this.Persona); } } private ICommand removeCommand; public ICommand RemoveCommand { get { return this.removeCommand = this.removeCommand ?? new MvxCommand(this.RemovePersona); } } private void RemovePersona() { this.userInteraction.Confirm("Are you sure?", () => { this.messenger.Publish(new RemovePersonaDenunciaMessage(this, this.Persona, this.Index)); }, null, "OK", "Cancel"); } } } 

Y ese último messenger.Publish está suscrito a esto en otro ViewModel

 OnRemovePersonaDenuncia = message => { var listPersonas = new ObservableCollection<PersonaDenunciaItemViewModel>(this.Personas); listPersonas.Remove(this.Personas.First(p => p.Index == message.Index)); this.Personas = listPersonas; } 

Actualizaciones

Cambiar la implementación de RemoveCommand a este

 this.Personas.Remove(this.Personas.First(p => p.Index == message.Index)); 

Hace que, cuando presiono el button quitar, el simulador se cierra sin ningún error. La traza de la aplicación en Xamarin Studio muestra esto

*** Error de aserción en – [UITableView _endCellAnimationsWithContext:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3512.60.7/UITableView.m:1700

iOS no calcula la altura de las celdas correctamente cuando la altura del contenido es dinámica. Eso es muy molesto, pero puedes anular GetHeightForRow y EstimatedHeight en SiniestroParticipantesSource para calcular la altura exacta de cada celda según los datos:

 public override nfloat EstimatedHeight(UITableView tableView, NSIndexPath indexPath) => GetHeightForRow(tableView, indexPath); public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath) { var data = (PersonaDenunciaItemViewModel)ItemsSource.ElementAt(indexPath.Row); var cell = (PersonaDenunciaCellView)tableView.DequeueReusableCell(PersonaDenunciaCellView.Key, indexPath); // TODO set the cell data manually (ignoring bindings) // ie: **cell.lblNombre = data.Persona.Persona.Nombre**; // and every other field requinetworking cell.SetNeedsLayout(); cell.LayoutIfNeeded(); var size = cell.ContentView.SystemLayoutSizeFittingSize(UIView.UILayoutFittingCompressedSize); return NMath.Ceiling(size.Height) + 1; } 

Aquí hay un ejemplo con el mismo código.