internal void UninitializeForContext(VirtualizingLayoutContext context) { FlowAlgorithm.UninitializeForContext(context); if (_cachedFirstElement != null) { context.RecycleElement(_cachedFirstElement); } }
internal void EnsureFirstElementOwnership(VirtualizingLayoutContext context) { if (_cachedFirstElement != null && FlowAlgorithm.GetElementIfRealized(0) != null) { // We created the element, but then flowlayout algorithm took ownership, so we can clear it and // let flowlayout algorithm do its thing. context.RecycleElement(_cachedFirstElement); _cachedFirstElement = null; } }
internal void ClearElementOnDataSourceChange( VirtualizingLayoutContext context, NotifyCollectionChangedEventArgs args) { if (_cachedFirstElement != null) { bool shouldClear = false; switch (args.Action) { case NotifyCollectionChangedAction.Add: shouldClear = args.NewStartingIndex == 0; break; case NotifyCollectionChangedAction.Replace: shouldClear = args.NewStartingIndex == 0 || args.OldStartingIndex == 0; break; case NotifyCollectionChangedAction.Remove: shouldClear = args.OldStartingIndex == 0; break; case NotifyCollectionChangedAction.Reset: shouldClear = true; break; case NotifyCollectionChangedAction.Move: throw new NotImplementedException(); } if (shouldClear) { context.RecycleElement(_cachedFirstElement); _cachedFirstElement = null; } } }
internal void RecycleElementAt(int index) { var element = _context.GetOrCreateElementAt(index); _context.RecycleElement(element); }
/// <inheritdoc /> protected internal override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize) { var totalMeasure = UvMeasure.Zero; var parentMeasure = new UvMeasure(Orientation, availableSize.Width, availableSize.Height); var spacingMeasure = new UvMeasure(Orientation, HorizontalSpacing, VerticalSpacing); var realizationBounds = new UvBounds(Orientation, context.RealizationRect); var position = UvMeasure.Zero; var state = (WrapLayoutState)context.LayoutState; if (state.Orientation != Orientation) { state.SetOrientation(Orientation); } if (spacingMeasure.Equals(state.Spacing) == false) { state.ClearPositions(); state.Spacing = spacingMeasure; } if (state.AvailableU != parentMeasure.U) { state.ClearPositions(); state.AvailableU = parentMeasure.U; } double currentV = 0; for (int i = 0; i < context.ItemCount; i++) { bool measured = false; WrapItem item = state.GetItemAt(i); if (item.Measure == null) { item.Element = context.GetOrCreateElementAt(i); item.Element.Measure(availableSize); item.Measure = new UvMeasure(Orientation, item.Element.DesiredSize.Width, item.Element.DesiredSize.Height); measured = true; } UvMeasure currentMeasure = item.Measure.Value; if (currentMeasure.U == 0) { continue; // ignore collapsed items } if (item.Position == null) { if (parentMeasure.U < position.U + currentMeasure.U) { // New Row position.U = 0; position.V += currentV + spacingMeasure.V; currentV = 0; } item.Position = position; } position = item.Position.Value; double vEnd = position.V + currentMeasure.V; if (vEnd < realizationBounds.VMin) { // Item is "above" the bounds if (item.Element != null) { context.RecycleElement(item.Element); item.Element = null; } } else if (position.V > realizationBounds.VMax) { // Item is "below" the bounds. if (item.Element != null) { context.RecycleElement(item.Element); item.Element = null; } // We don't need to measure anything below the bounds break; } else if (measured == false) { // Always measure elements that are within the bounds item.Element = context.GetOrCreateElementAt(i); item.Element.Measure(availableSize); currentMeasure = new UvMeasure(Orientation, item.Element.DesiredSize.Width, item.Element.DesiredSize.Height); if (currentMeasure.Equals(item.Measure) == false) { // this item changed size; we need to recalculate layout for everything after this state.RemoveFromIndex(i + 1); item.Measure = currentMeasure; // did the change make it go into the new row? if (parentMeasure.U < position.U + currentMeasure.U) { // New Row position.U = 0; position.V += currentV + spacingMeasure.V; currentV = 0; } item.Position = position; } } position.U += currentMeasure.U + spacingMeasure.U; currentV = Math.Max(currentMeasure.V, currentV); } // update value with the last line // if the the last loop is(parentMeasure.U > currentMeasure.U + lineMeasure.U) the total isn't calculated then calculate it // if the last loop is (parentMeasure.U > currentMeasure.U) the currentMeasure isn't added to the total so add it here // for the last condition it is zeros so adding it will make no difference // this way is faster than an if condition in every loop for checking the last item totalMeasure.U = parentMeasure.U; totalMeasure.V = state.GetHeight(); totalMeasure.U = Math.Ceiling(totalMeasure.U); return(Orientation == Orientation.Horizontal ? new Size(totalMeasure.U, totalMeasure.V) : new Size(totalMeasure.V, totalMeasure.U)); }