private void AddItemsToPresenter(GeneratorPosition position, int count) { if (this.itemsPresenter == null || this.itemsPresenter.Child == null || this.itemsPresenter.Child is VirtualizingPanel) { return; } Panel panel = this.itemsPresenter.Child; int newIndex = this.ItemContainerGenerator.IndexFromGeneratorPosition(position); using (IDisposable p = ItemContainerGenerator.StartAt(position, GeneratorDirection.Forward, true)) { for (int i = 0; i < count; i++) { object item = this.Items[newIndex + i]; DependencyObject container = null; bool fresh; container = this.ItemContainerGenerator.GenerateNext(out fresh); FrameworkElement f = container as FrameworkElement; if (f != null && !(item is FrameworkElement)) { f.DataContext = item; } panel.InternalChildren.Insert(newIndex + i, (UIElement)container); this.ItemContainerGenerator.PrepareItemContainer(container); } } }
private void RemoveItemsFromPresenter(GeneratorPosition position, int count) { if (this.itemsPresenter == null || this.itemsPresenter.Child == null || this.itemsPresenter.Child is VirtualizingPanel) { return; } Panel panel = this.itemsPresenter.Child; while (count-- > 0) { panel.InternalChildren.RemoveAt(position.Index); } }
internal void Recycle(GeneratorPosition position, int count) { this.CheckOffsetAndRealized(position, count); int index = this.IndexFromGeneratorPosition(position); for (int i = 0; i < count; i++) { this.Cache.Enqueue(this.ContainerIndexMap[index + i]); } this.Remove(position, count); }
private void CheckOffsetAndRealized(GeneratorPosition position, int count) { if (position.Offset != 0) { throw new ArgumentException("position.Offset must be zero as the position must refer to a realized element."); } int index = this.IndexFromGeneratorPosition(position); int rangeIndex = this.RealizedElements.FindRangeIndexForValue(index); RangeCollection.Range range = this.RealizedElements.Ranges[rangeIndex]; if (index < range.Start || (index + count) > range.Start + range.Count) { throw new InvalidOperationException("Only items which have been Realized can be removed."); } }
internal void Remove(GeneratorPosition position, int count) { this.CheckOffsetAndRealized(position, count); int index = this.IndexFromGeneratorPosition(position); for (int i = 0; i < count; i++) { var container = this.ContainerIndexMap[index + i]; var item = this.ContainerItemMap[container]; this.ContainerIndexMap.Remove(container, index + i); this.ContainerItemMap.Remove(container); this.RealizedElements.Remove(index + i); this.Owner.ClearContainerForItem(container, item); } }
internal IDisposable StartAt( GeneratorPosition position, GeneratorDirection direction, bool allowStartAtRealizedItem) { if (GenerationState != null) { throw new InvalidOperationException("Cannot call StartAt while a generation operation is in progress"); } GenerationState = new GenerationState { AllowStartAtRealizedItem = allowStartAtRealizedItem, Direction = direction, Position = position, Generator = this }; return GenerationState; }
internal void OnOwnerItemsItemsChanged(object sender, NotifyCollectionChangedEventArgs e) { int itemCount; int itemUICount; GeneratorPosition oldPosition = new GeneratorPosition(-1, 0); GeneratorPosition position; switch (e.Action) { case NotifyCollectionChangedAction.Add: if ((e.NewStartingIndex + 1) != this.Owner.Items.Count) { this.MoveExistingItems(e.NewStartingIndex, 1); } itemCount = 1; itemUICount = 0; position = this.GeneratorPositionFromIndex(e.NewStartingIndex); break; case NotifyCollectionChangedAction.Remove: itemCount = 1; itemUICount = this.RealizedElements.Contains(e.OldStartingIndex) ? 1 : 0; position = this.GeneratorPositionFromIndex(e.OldStartingIndex); if (itemUICount == 1) { this.Remove(position, 1); } this.MoveExistingItems(e.OldStartingIndex, -1); break; case NotifyCollectionChangedAction.Replace: if (!this.RealizedElements.Contains(e.NewStartingIndex)) { return; } itemCount = 1; itemUICount = 1; position = this.GeneratorPositionFromIndex(e.NewStartingIndex); this.Remove(position, 1); bool fresh; var newPos = this.GeneratorPositionFromIndex(e.NewStartingIndex); using (this.StartAt(newPos, GeneratorDirection.Forward, true)) { this.PrepareItemContainer(this.GenerateNext(out fresh)); } break; case NotifyCollectionChangedAction.Reset: itemCount = e.OldItems == null ? 0 : e.OldItems.Count; itemUICount = this.RealizedElements.Count; position = new GeneratorPosition(-1, 0); this.RemoveAll(); break; default: Console.WriteLine("*** Critical error in ItemContainerGenerator.OnOwnerItemsItemsChanged. NotifyCollectionChangedAction.{0} is not supported", e.Action); return; } ItemsChangedEventArgs args = new ItemsChangedEventArgs { Action = e.Action, ItemCount = itemCount, ItemUICount = itemUICount, OldPosition = oldPosition, Position = position }; var h = this.ItemsChanged; if (h != null) { h(this, args); } }
void IRecyclingItemContainerGenerator.Recycle(GeneratorPosition position, int count) { this.Recycle(position, count); }
IDisposable IItemContainerGenerator.StartAt( GeneratorPosition position, GeneratorDirection direction, bool allowStartAtRealizedItem) { return this.StartAt(position, direction, allowStartAtRealizedItem); }
void IItemContainerGenerator.Remove(GeneratorPosition position, int count) { this.Remove(position, count); }
public int IndexFromGeneratorPosition(GeneratorPosition position) { // We either have everything realised or nothing realised, so we can // simply just add Index and Offset together to get the right index (i think) if (position.Index == -1) { if (position.Offset < 0) { return this.Owner.Items.Count + position.Offset; } else { return position.Offset - 1; } } else { if (position.Index > this.Owner.Items.Count) { return -1; } if (position.Index >= 0 && position.Index < this.RealizedElements.Count) { return this.RealizedElements[position.Index] + position.Offset; } return position.Index + position.Offset; } }