protected override Size MeasureOverride(Size availableSize) { if (m_isLayoutInProgress) { throw new Exception("Reentrancy detected during layout."); } if (IsProcessingCollectionChange) { throw new Exception("Cannot run layout in the middle of a collection change."); } m_viewportManager.OnOwnerMeasuring(); m_isLayoutInProgress = true; try { ViewManager.PrunePinnedElements(); Rect extent = default; Size desiredSize = default; if (Layout is Layout layout) { var layoutContext = GetLayoutContext(); // Checking if we have an data template and it is empty if (m_isItemTemplateEmpty) { // Has no content, so we will draw nothing and request zero space extent = new Rect(m_layoutOrigin.X, m_layoutOrigin.Y, 0, 0); } else { desiredSize = layout.Measure(layoutContext, availableSize); extent = new Rect(m_layoutOrigin.X, m_layoutOrigin.Y, desiredSize.Width, desiredSize.Height); } // Clear auto recycle candidate elements that have not been kept alive by layout - i.e layout did not // call GetElementAt(index). var children = Children; for (int i = 0; i < children.Count; ++i) { var element = children[i]; var virtInfo = GetVirtualizationInfo(element); if (virtInfo.Owner == ElementOwner.Layout && virtInfo.AutoRecycleCandidate && !virtInfo.KeepAlive) { ClearElementImpl(element); } } } m_viewportManager.SetLayoutExtent(extent); m_lastAvailableSize = availableSize; m_lastChildDesiredSizeChangedCounter = m_childDesiredSizeChangedCounter = 0; return(desiredSize); } finally { m_isLayoutInProgress = false; } }
protected override Size ArrangeOverride(Size finalSize) { if (m_isLayoutInProgress) { throw new Exception("Reentrancy detected during layout."); } if (IsProcessingCollectionChange) { throw new Exception("Cannot run layout in the middle of a collection change."); } m_isLayoutInProgress = true; try { Size arrangeSize = default; if (Layout is Layout layout) { arrangeSize = layout.Arrange(GetLayoutContext(), finalSize); } // The view manager might clear elements during this call. // That's why we call it before arranging cleared elements // off screen. ViewManager.OnOwnerArranged(); var children = Children; for (int i = 0; i < children.Count; ++i) { var element = children[i]; var virtInfo = GetVirtualizationInfo(element); virtInfo.KeepAlive = false; if (virtInfo.Owner == ElementOwner.ElementFactory || virtInfo.Owner == ElementOwner.PinnedPool) { // Toss it away. And arrange it with size 0 so that XYFocus won't use it. element.Arrange(new Rect( ClearedElementsArrangePosition.X - element.DesiredSize.Width, ClearedElementsArrangePosition.Y - element.DesiredSize.Height, 0.0, 0.0)); } else { var newBounds = CachedVisualTreeHelpers.GetLayoutSlot(element as FrameworkElement); if (virtInfo.ArrangeBounds != InvalidRect && newBounds != virtInfo.ArrangeBounds) { AnimationManager.OnElementBoundsChanged(element, virtInfo.ArrangeBounds, newBounds); } virtInfo.ArrangeBounds = newBounds; } } m_viewportManager.OnOwnerArranged(); AnimationManager.OnOwnerArranged(); return(arrangeSize); } finally { m_isLayoutInProgress = false; } }