問題
你問的什麼錯誤,以及說明如何解決的解釋說明它。到目前爲止,沒有人解釋這個問題。我會照辦的。
在具有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