/// <summary> /// Arrange the children /// </summary> /// <param name="finalSize">Size available</param> /// <returns>Size used</returns> protected override Size ArrangeOverride(Size finalSize) { ItemsControl itemsControl = ItemsControl.GetItemsOwner(this); TreeViewExItem treeViewItem = itemsControl as TreeViewExItem; TreeViewEx treeView = itemsControl as TreeViewEx ?? treeViewItem.ParentTreeView; IItemContainerGenerator generator = this.ItemContainerGenerator; //Extent = finalSize; bool foundVisibleItem = false;; double currentY = 0; if (treeView.IsVirtualizing) { for (int i = 0; i < itemsControl.Items.Count; i++) { FrameworkElement child = itemsControl.ItemContainerGenerator.ContainerFromIndex(i) as FrameworkElement; if (foundVisibleItem) { if (child == null) { // other items are not visible / virtualized break; } } else { if (child != null) { // found first visible item foundVisibleItem = true; } } if (child != null) { child.Arrange(new Rect(-HorizontalOffset, currentY - VerticalOffset, finalSize.Width, child.DesiredSize.Height)); currentY += child.ActualHeight; } else { currentY += GetContainerHeightForItem(itemsControl, i); } } // update average after arrange, because we have to use the same average as in measure for our calculation of currentY. cachedSizes.Update(); } else { for (int i = 0; i < itemsControl.Items.Count; i++) { UIElement child = itemsControl.ItemContainerGenerator.ContainerFromIndex(i) as UIElement; if (child != null) { child.Arrange(new Rect(-HorizontalOffset, currentY - VerticalOffset, finalSize.Width, child.DesiredSize.Height)); } currentY += child.DesiredSize.Height; } } return(finalSize); }