UITableViewDelegate问题 – RowSelected给出了错误的NSIndexPath
我有我已经分类的UITableViewSource。 我重写GetCell和使用我自己的subclassed单元格,如下所示:
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath) { MarketItem item=_tableItems[indexPath.Section].Items[indexPath.Row]; MarketCell cell=tableView.DequeueReusableCell(_cellIdentifier) as MarketCell; if (cell==null) { cell=new MarketCell(UITableViewCellStyle.Subtitle,_cellIdentifier,item); } // decorate the cell // ... return cell; }
这工作,但是当我得到我的UITableViewDelegate事件,索引path得到我错误的单元格(像AccessoryButtonTapped,WillSelectRow等事件)。
部分和行号看起来是正确的,但是当我做一个
tableView.CellAt(indexPath)
我得到错误的单元格。 (行和段号再次看起来是正确的。)
注意事项:
- 表不断更新 – 项目到达不同的线程然后InvokeOnMainThread'd
- 虽然表格不断更新,但只添加了行和部分 – 没有重新sorting或删除
- 如果我在获取“WillSelectRow”的时候暂停更新,这并没有帮助
- 最有趣的是(但不是一个可交付的解决scheme),如果我每次做一个新的单元而不是做DequeueReusableCell,它能正常工作。
我不禁认为这是我自己制造的一个愚蠢的错误,但无法find它。 任何帮助将非常感激地收到!
你可以尝试一种不同的方法,如http://simon.nureality.ca/?p=91所示
基本上,不要inheritanceUITableViewCell,而是将UIViewController作为“MarketCellController”的子类。 这个自定义控制器维护一个标准的UITableViewCell以及你的自定义的东西,并简单地通过AddSubview()添加你的自定义的东西。
您为每个必需的单元格创build一个新的控制器并将其存储到字典中。
诀窍:通过为单元分配唯一标记,您可以从字典中检索关联的控制器。
快速示例:
Dictionary<int,MarketCellController> controllers = new Dictionary<int,MarketCellController>(); // ... public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath) { UITableViewCell cell = tableView.DequeueReusableCell(_cellIdentifier); MarketCellController cellController; if (cell == null) { cellController = new MarketCellController(); cell = cellController.Cell; controllers.Add(cell.Tag, cellController); } else { cellController = controllers[cell.Tag]; } // Decorate the cell (using Methods of your cellController) // ... return cell; }
这可能最终会绕过UITableViewCells和出队的问题。
编辑:
我只是有一些其他的想法:你似乎只在你的MarketCell构造函数上分配你的项目。 但是,出列单元格的旧项目已设置,您需要在出列之后将其重置为新项目。
删除构造函数的item参数(它将被覆盖),并创build一个公共属性(或setter)。 在获取单元格之后使用它来分配正确的项目(不pipe它是否已经出队或新创build)。 应该这样做:
MarketCell cell = tableView.DequeueReusableCell(_cellIdentifier) as MarketCell; if (cell == null) { cell = new MarketCell(UITableViewCellStyle.Subtitle, _cellIdentifier); } // Assign the correct item cell.Item = item; // or (whatever you like more): // cell.SetItem(item); // Decorate the cell // ... return cell;
我的cellController方法也是如此。 无论细胞出院还是新出现,都应该重置细胞上可能与其他细胞不同的所有细胞。
顺便说一句:如果你硬编码你的单元格到UITableViewCellStyle.Subtitle,你可以从构造函数中忽略它,并将其硬编码到你的MarketCell类中。
至于cellController的方法是值得的:你从你的自定义数据和行为中解耦UITableViewCell,从而得到一个很好的分离层。 您的单元格控制器不必像表格单元格一样工作;)
看来这在Xamarin中还是个问题。 @ vlad259发布的链接不幸已经消失了很久了,而这个“bug”就是今天的一点点。 我不知道为什么会发生这种情况 – 为了追踪原因,我使用了裁减我的UITableViewSource实现,直到返回固定数量的行,并简单地将行号分配给单元格标签。 ..
这个bug具体performance为:加载视图,滚动到第一个屏幕外的单元格(例如,如果你的表格可以渲染10个单元格,滚动到第11个单元格出现在屏幕上),然后点击该单元格 – 你会得到一个几乎是随机的RowSelected事件中的行索引。
我find了一些解决scheme。
答案A
如果我重写了GetHeightForRow
来返回自定义行高,这个bug只会出现,即使它返回一个常量。 如果不需要…不要覆盖它。
解决schemeB
看来,该错误是专门在DequeueReusableCell
(s)接受NSIndexPath
参数。
使用
UITableView.DequeueReusableCell(NSString)
代替
UITableView.DequeueReusableCell(NSString, NSIndexPath)