问题
你问的什么错误,以及说明如何解决的解释说明它。到目前为止,没有人解释这个问题。我会照办的。
在具有VirtualizingWrapPanel列表框有跟踪项目,每个项目以不同的方式五个独立的数据结构:
- 的ItemsSource:原来的集合(在这种情况下的ObservableCollection)
- 的CollectionView:保持一个单独的列表排序/过滤/分组项目(仅当使用这些功能中的任何一个时)
- ItemContainerGenerator:跟踪项目和容器之间的映射
- InternalChildren:跟踪当前可见的容器勒
- WrapPanelAbstraction:跟踪哪些容器出现在哪一行
当物品从的ItemsSource去除,该去除必须通过所有的数据结构被传播。下面是它如何工作的:
- 您呼吁的ItemsSource
- 的ItemsSource删除()移除该项目,并触发其CollectionChanged这是由的CollectionView
- 的CollectionView处理删除的项目(如排序/过滤/分组是在使用中),并触发其CollectionChanged其由ItemContainerGenerator
- ItemContainerGenerator更新其映射处理,触发其ItemsChanged其通过VirtualizingPanel处理
- VirtualizingPanel调用其虚拟OnItemsChanged方法whic h由VirtualizingWrapPanel实现
- VirtualizingWrapPanel放弃其WrapPanelAbstraction所以将建成,但它永远不会更新InternalChildren
正因为如此,在InternalChildren收集了与其他四个集合同步,导致经历过的错误。
解决问题
要解决此问题,任意位置添加以下代码VirtualizingWrapPanel的OnItemsChanged方法中:
switch(args.Action)
{
case NotifyCollectionChangedAction.Remove:
case NotifyCollectionChangedAction.Replace:
RemoveInternalChildRange(args.Position.Index, args.ItemUICount);
break;
case NotifyCollectionChangedAction.Move:
RemoveInternalChildRange(args.OldPosition.Index, args.ItemUICount);
break;
}
这样可以使InternalChildren集合中同步与其他数据结构。
为什么AddInternalChild/InsertInternalChild这里不叫
你可能想知道为什么在上面的代码InsertInternalChild或AddInternalChild没有电话,特别是为什么处理更换和移动并不需要我们添加一个OnItemsChanged期间的新项目。
理解这一点的关键在于ItemContainerGenerator的工作方式。
当ItemContainerGenerator接收它处理的一切立即删除事件:
- ItemContainerGenerator立即从自己的数据结构
- ItemContainerGenerator将触发ItemChanged事件中删除的项目。预计该小组将立即移除该容器。
- ItemContainerGenerator“都会使得准备”通过去除其的DataContext
在另一方面,容器,ItemContainerGenerator得知项目被添加一切通常推迟:
- ItemContainerGenerator立即增加了一个“槽”为该项目在其数据结构中但不创建容器
- ItemContainerGenerator触发ItemChanged事件。面板调用InvalidateMeasure()[这是由基类完成的 - 你不必这样做]
- 稍后当调用MeasureOverride时,Generator.StartAt/MoveNext用于生成项容器。任何新生成的容器当时都会被添加到InternalChildren中。
因此,从InternalChildren集合(包括那些是移动的部位或更换)全部清除里面必须要OnItemsChanged做,但增加的部分可以(也应该)被推迟,直到下一次的MeasureOverride。
看起来像Tom Goff在输入我的答案时提供了必要的代码。他的回答也是正确的,如果没有详细的解释,基本上和我一样。 – 2010-08-18 21:15:07
嗨雷 - 尼斯总结,你有我的投票。答案的一个问题是,问题不在于“InternalChildren集合与其他四个集合不同步”,但我相信它没有帮助。 潜在的问题是,实现的孩子没有“清理”。如果您删除了索引为10的项目,那么索引为11的项目将被移至索引10.当您在索引10(先前为11)处实现该项目时,您将最终断言“错误的孩子被生成“,因为另一个孩子从未被实现。 – CodeNaked 2010-08-19 13:23:06