private Size ArrangeColumn(VirtualizingLayoutContext context, GroupedLayoutState state, ColumnInfo colInfo, int col, int headerIndex, double startingY, bool widthChanged, out int nextHeaderIndex) { // Note that you MUST call GetOrCreateElement on any items that are in the realized region... that's how // the control tracks which elements it shouldn't dispose. double y = startingY; double x = col * colInfo.ColumnWidth + ColumnSpacing * col; int i = headerIndex; var header = state.GetItemAt(headerIndex); var headerEl = context.GetOrCreateElementAt(headerIndex); headerEl.Arrange(new Rect(x, y, colInfo.ColumnWidth, headerEl.DesiredSize.Height)); y += headerEl.DesiredSize.Height + AfterHeaderSpacing; i++; while (i < context.ItemCount) { if (!(context.GetItemAt(i) is ViewItemTaskOrEvent)) { // End of column break; } var item = state.GetItemAt(i); // Logic technically ignores height of item, but heights are short enough it shouldn't matter if (y < context.RealizationRect.Top || y > context.RealizationRect.Bottom) { y += item.Height.GetValueOrDefault(40); } else { var el = context.GetOrCreateElementAt(i); //if (widthChanged || !item.Arranged) { el.Arrange(new Rect(x, y, colInfo.ColumnWidth, el.DesiredSize.Height)); } y += el.DesiredSize.Height; } // Include item spacing y += ItemSpacing; i++; } // Remove last item spacing (since no item after it) y -= ItemSpacing; nextHeaderIndex = i; return(new Size(colInfo.ColumnWidth, y - startingY)); }
private Size MeasureColumn(VirtualizingLayoutContext context, GroupedLayoutState state, Size availableSizeForElements, int headerIndex, double startingY, bool widthChanged, out int nextHeaderIndex) { // Note that you MUST call GetOrCreateElement on any items that are in the realized region... that's how // the control tracks which elements it shouldn't dispose. double y = startingY; int i = headerIndex; var header = state.GetItemAt(headerIndex); //if (widthChanged || header.Height == null) { var headerEl = context.GetOrCreateElementAt(headerIndex); headerEl.Measure(availableSizeForElements); header.Height = headerEl.DesiredSize.Height; } y += header.Height.Value + AfterHeaderSpacing; i++; while (i < context.ItemCount) { if (!(context.GetItemAt(i) is ViewItemTaskOrEvent)) { // End of column break; } var item = state.GetItemAt(i); // Logic technically ignores height of item, but heights are short enough it shouldn't matter if (y < context.RealizationRect.Top || y > context.RealizationRect.Bottom) { y += item.Height.GetValueOrDefault(40); } else { // Theoretically since tasks/events are removed and then added back when edited, we know they can never change size... // Therefore we can store their measured size, and only call measure if their width changed or height unknown... // However this didn't work in reality, not sure why. //if (widthChanged || item.Height == null) { var itemEl = context.GetOrCreateElementAt(i); itemEl.Measure(availableSizeForElements); item.Height = itemEl.DesiredSize.Height; } y += item.Height.Value; } // Include item spacing y += ItemSpacing; i++; } // Remove last item spacing (since no item after it) y -= ItemSpacing; nextHeaderIndex = i; return(new Size(availableSizeForElements.Width, y - startingY)); }