private Size MeasureOverride(Size availableSize, List <RenderableBlockAndElement> children) { // Reset all foreach (var child in children) { child.RenderableBlock.Reset(); } double consumedHeight = 0; double remainingHeight = availableSize.Height; double maxWidth = 0; for (int i = 0; i < children.Count; i++) { var child = children[i]; if (child.RenderableBlock.IsColumn) { var columnGroup = children.Skip(i).TakeWhile(x => x.RenderableBlock.IsColumn).ToArray(); // See how many columns fit double colsRemainingHeight = remainingHeight; double colsConsumedHeight = consumedHeight; double colsMaxWidth = maxWidth; int colsThatFit = MeasureAsCols(columnGroup, availableSize.Width, ref colsRemainingHeight, ref colsConsumedHeight, ref colsMaxWidth); // If they'll all fit, perfect! if (colsThatFit == columnGroup.Length) { remainingHeight = colsRemainingHeight; consumedHeight = colsConsumedHeight; maxWidth = colsMaxWidth; i += columnGroup.Length - 1; foreach (var c in columnGroup) { c.RenderableBlock.IsDropped = false; } continue; } // Otherwise, try render as rows and see if that fits more foreach (var c in columnGroup) { c.RenderableBlock.IsColumn = false; } double rowsRemainingHeight = remainingHeight; double rowsConsumedHeight = consumedHeight; double rowsMaxWidth = maxWidth; int rowsThatFit = MeasureAsRows(columnGroup, availableSize.Width, ref rowsRemainingHeight, ref rowsConsumedHeight, ref rowsMaxWidth); System.Diagnostics.Debug.WriteLine("Rows: " + rowsThatFit + ", Cols: " + colsThatFit); // If any non-optional blocks don't fit, simplify if (columnGroup.Skip(Math.Max(colsThatFit, rowsThatFit)).Any(x => !x.RenderableBlock.BlockSource.Optional)) { return(MeasureOverrideOneLevelSimplified(availableSize, children)); } // If more fit as rows, leave it as rows if (rowsThatFit > colsThatFit) { remainingHeight = rowsRemainingHeight; consumedHeight = rowsConsumedHeight; maxWidth = rowsMaxWidth; i += columnGroup.Length - 1; foreach (var c in columnGroup.Take(rowsThatFit)) { c.RenderableBlock.IsDropped = false; } continue; } // Otherwise, revert it back to columns foreach (var c in columnGroup) { c.RenderableBlock.IsColumn = true; } // And re-measure for columns MeasureAsCols(columnGroup.Take(colsThatFit), availableSize.Width, ref remainingHeight, ref consumedHeight, ref maxWidth); i += columnGroup.Length - 1; foreach (var c in columnGroup.Take(colsThatFit)) { c.RenderableBlock.IsDropped = false; } continue; } else if (child.RenderableBlock.IsFactSet) { var factSetGroup = children.Skip(i).TakeWhile(x => x.RenderableBlock.IsFactSet).ToArray(); double factRemainingHeight = remainingHeight; double factConsumedHeight = consumedHeight; double factMaxWidth = maxWidth; foreach (var f in factSetGroup) { MeasureAsRow(f, availableSize.Width, ref factRemainingHeight, ref factConsumedHeight, ref factMaxWidth); } if (factSetGroup.All(x => VisualTreeHelpers.Find <FactSetItemControl>(x.Element).FitsComfortably())) { foreach (var f in factSetGroup) { f.RenderableBlock.IsDropped = false; } i += factSetGroup.Length - 1; continue; } foreach (var f in factSetGroup) { f.RenderableBlock.IsFactSet = false; } // Let continue to normal rows } if (MeasureAsRow(child, availableSize.Width, ref remainingHeight, ref consumedHeight, ref maxWidth)) { child.RenderableBlock.IsDropped = false; } else { // If this block was required if (!child.RenderableBlock.BlockSource.Optional) { return(MeasureOverrideOneLevelSimplified(availableSize, children)); } break; } } return(new Size(maxWidth, consumedHeight)); }