private void ArrangeChildren() { var isHorizontal = this.Orientation == Orientation.Horizontal; var rowCount = this.RowDefinitions.Count; var columnCount = this.ColumnDefinitions.Count; if (isHorizontal && rowCount == 0 || !isHorizontal && columnCount == 0) { return; } var position = 0; foreach (UIElement child in Children) { if (isHorizontal) { var row = Math.Min(position % rowCount, rowCount - 1); var col = position / rowCount; Grid.SetRow(child, row); Grid.SetColumn(child, col); position++; } else { var row = position / columnCount; var col = Math.Min(position % columnCount, columnCount - 1); if (row >= rowCount) { RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto }); } Grid.SetRow(child, row); Grid.SetColumn(child, col); position++; } } if (isHorizontal) { var totalCols = (position / rowCount) + 1; if (totalCols < columnCount) { ColumnDefinitions.RemoveRange(totalCols - 1, columnCount - totalCols); } } else { var totalRows = (position / columnCount) + 1; if (totalRows < rowCount) { RowDefinitions.RemoveRange(totalRows, rowCount - totalRows); } } }
public void ReduceRows(int newSize) { List <UIElement> elements = new List <UIElement>(); foreach (UIElement element in Children) { if (GetRow(element) > newSize - 1) { elements.Add(element); } } foreach (UIElement element in elements) { Children.Remove(element); } RowDefinitions.RemoveRange(newSize - 1, RowDefinitions.Count - newSize); }
/// <summary> /// Measures the children of a <see cref="T:System.Windows.Controls.Grid"/> in anticipation of arranging them during the <see cref="FrameworkElement.ArrangeOverride"/> pass. /// </summary> /// <param name="constraint">Indicates an upper limit size that should not be exceeded.</param> /// <returns> /// <see cref="Size"/> that represents the required size to arrange child content. /// </returns> protected override Size MeasureOverride(Size constraint) { using (_layoutScope.Enter()) { var isVertical = Orientation == Orientation.Vertical; if (_shouldReindex || (IsAutoIndexing && ((isVertical && _rowOrColumnCount != ColumnDefinitions.Count) || (!isVertical && _rowOrColumnCount != RowDefinitions.Count)))) { _shouldReindex = false; if (IsAutoIndexing) { _rowOrColumnCount = (isVertical) ? ColumnDefinitions.Count : RowDefinitions.Count; if (_rowOrColumnCount == 0) { _rowOrColumnCount = 1; } var cellCount = 0; var currentRow = 0; var currentColumn = 0; var reservedPositions = new HashSet <ReservedPosition>(); foreach (UIElement child in Children) { ChildLayoutInfo layoutInfo; if (!_childData.TryGetValue(child, out layoutInfo)) { layoutInfo = new ChildLayoutInfo { OriginalColumn = Undefined, OriginalRow = Undefined }; if (!child.HasDefaultValue(ColumnProperty)) { layoutInfo.OriginalColumn = GetColumn(child); if ((Orientation == Orientation.Vertical) && (layoutInfo.OriginalColumn >= ColumnDefinitions.Count)) { layoutInfo.OriginalColumn = ColumnDefinitions.Count - 1; } } if (!child.HasDefaultValue(RowProperty)) { layoutInfo.OriginalRow = GetRow(child); if ((Orientation == Orientation.Horizontal) && (layoutInfo.OriginalRow >= RowDefinitions.Count)) { layoutInfo.OriginalRow = RowDefinitions.Count - 1; } } _childData[child] = layoutInfo; } if (layoutInfo.OriginalColumn != Undefined) { if (layoutInfo.OriginalRow != Undefined) { layoutInfo.ActualColumn = layoutInfo.OriginalColumn; layoutInfo.ActualRow = layoutInfo.OriginalRow; reservedPositions.Add( new ReservedPosition( layoutInfo.ActualColumn, layoutInfo.ActualRow)); } else if (isVertical) { while ((layoutInfo.OriginalColumn != currentColumn) || reservedPositions.Contains(new ReservedPosition(currentRow, currentColumn))) { ++cellCount; if (++currentColumn >= _rowOrColumnCount) { currentColumn = 0; ++currentRow; } } layoutInfo.ActualRow = currentRow; layoutInfo.ActualColumn = currentColumn; } } else if (layoutInfo.OriginalRow != Undefined) { if (!isVertical) { while ((layoutInfo.OriginalRow != currentRow) || reservedPositions.Contains(new ReservedPosition(currentRow, currentColumn))) { ++cellCount; if (++currentRow >= _rowOrColumnCount) { currentRow = 0; ++currentColumn; } } layoutInfo.ActualRow = currentRow; layoutInfo.ActualColumn = currentColumn; } } else { while (reservedPositions.Contains(new ReservedPosition(currentRow, currentColumn))) { ++cellCount; if (isVertical) { if (++currentColumn >= _rowOrColumnCount) { currentColumn = 0; ++currentRow; } } else { if (++currentRow >= _rowOrColumnCount) { currentRow = 0; ++currentColumn; } } } layoutInfo.ActualColumn = currentColumn; layoutInfo.ActualRow = currentRow; } ++cellCount; SetRow(child, layoutInfo.ActualRow); SetColumn(child, layoutInfo.ActualColumn); var childRowSpan = GetRowSpan(child); var childColumnSpan = GetColumnSpan(child); if (isVertical) { if (!child.HasDefaultValue(ColumnSpanProperty)) { if ((currentColumn + childColumnSpan) >= _rowOrColumnCount) { childColumnSpan -= ((currentColumn + childColumnSpan) - _rowOrColumnCount - 1); } cellCount += childRowSpan * childColumnSpan; for (var i = 0; i < (childColumnSpan - 1); i++) { reservedPositions.Add(new ReservedPosition(currentRow, currentColumn + i)); } } if (!child.HasDefaultValue(RowSpanProperty)) { cellCount += childRowSpan * childColumnSpan; for (var i = 0; i < (childRowSpan - 1); i++) { reservedPositions.Add(new ReservedPosition(currentRow + i, currentColumn)); } } else if (++currentColumn >= _rowOrColumnCount) { currentColumn = 0; ++currentRow; } } else { if (!child.HasDefaultValue(RowSpanProperty)) { if ((currentColumn + childRowSpan) >= _rowOrColumnCount) { childRowSpan -= ((currentColumn + childRowSpan) - _rowOrColumnCount - 1); } cellCount += childRowSpan * childColumnSpan; for (var i = 0; i < (childRowSpan - 1); i++) { reservedPositions.Add(new ReservedPosition(currentRow + i, currentColumn)); } } if (!child.HasDefaultValue(ColumnSpanProperty)) { cellCount += childRowSpan * childColumnSpan; for (var i = 0; i < (childColumnSpan - 1); i++) { reservedPositions.Add(new ReservedPosition(currentRow, currentColumn + i)); } } else if (++currentRow >= _rowOrColumnCount) { currentRow = 0; ++currentColumn; } } } // Update the number of rows/columns if (isVertical) { int newRowCount = ((cellCount - 1) / _rowOrColumnCount + 1); while (RowDefinitions.Count < newRowCount) { RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); } if (RowDefinitions.Count > newRowCount) { RowDefinitions.RemoveRange(newRowCount, RowDefinitions.Count - newRowCount); } } else // horizontal { int newColumnCount = ((cellCount - 1) / _rowOrColumnCount + 1); while (ColumnDefinitions.Count < newColumnCount) { ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); } if (ColumnDefinitions.Count > newColumnCount) { ColumnDefinitions.RemoveRange(newColumnCount, ColumnDefinitions.Count - newColumnCount); } } } // Set margin and alignment foreach (UIElement child in Children) { if (ChildMargin != null) { child.SetIfDefault(MarginProperty, ChildMargin.Value); } if (ChildHorizontalAlignment != null) { child.SetIfDefault(HorizontalAlignmentProperty, ChildHorizontalAlignment.Value); } if (ChildVerticalAlignment != null) { child.SetIfDefault(VerticalAlignmentProperty, ChildVerticalAlignment.Value); } } } return(base.MeasureOverride(constraint)); } }
public void PerformLayout() { bool isVertical = Orientation == Orientation.Vertical; if (_shouldReindex || (IsAutoIndexing && ((isVertical && _rowOrColumnCount != ColumnDefinitions.Count) || (!isVertical && _rowOrColumnCount != RowDefinitions.Count)))) { _shouldReindex = false; if (IsAutoIndexing) { _rowOrColumnCount = (ColumnDefinitions.Count != 0) ? ColumnDefinitions.Count : RowDefinitions.Count; if (_rowOrColumnCount == 0) { _rowOrColumnCount = 1; } int cellCount = 0; foreach (UIElement child in Children) { if (GetAutoIndex(child) == false) { continue; } cellCount += (ColumnDefinitions.Count != 0) ? Grid.GetColumnSpan(child) : Grid.GetRowSpan(child); } // Update the number of rows/columns if (ColumnDefinitions.Count != 0) { var newRowCount = (int)Math.Ceiling((double)cellCount / (double)_rowOrColumnCount); while (RowDefinitions.Count < newRowCount) { var rowDefinition = new RowDefinition(); rowDefinition.Height = RowHeight; RowDefinitions.Add(rowDefinition); } if (RowDefinitions.Count > newRowCount) { RowDefinitions.RemoveRange(newRowCount, RowDefinitions.Count - newRowCount); } } else // rows defined { var newColumnCount = (int)Math.Ceiling((double)cellCount / (double)_rowOrColumnCount); while (ColumnDefinitions.Count < newColumnCount) { var columnDefinition = new ColumnDefinition(); columnDefinition.Width = ColumnWidth; ColumnDefinitions.Add(columnDefinition); } if (ColumnDefinitions.Count > newColumnCount) { ColumnDefinitions.RemoveRange(newColumnCount, ColumnDefinitions.Count - newColumnCount); } } } // Update children indices int cellPosition = 0; var cellsToSkip = new Queue <int>(); foreach (UIElement child in Children) { if (IsAutoIndexing && GetAutoIndex(child) == true) { if (cellsToSkip.Any() && cellsToSkip.Peek() == cellPosition) { cellsToSkip.Dequeue(); cellPosition += 1; } if (!isVertical) // horizontal (default) { var rowIndex = cellPosition / ColumnDefinitions.Count; Grid.SetRow(child, rowIndex); var columnIndex = cellPosition % ColumnDefinitions.Count; Grid.SetColumn(child, columnIndex); var rowSpan = Grid.GetRowSpan(child); if (rowSpan > 1) { Enumerable.Range(1, rowSpan).ToList() .ForEach(x => cellsToSkip.Enqueue(cellPosition + ColumnDefinitions.Count * x)); } var overrideRowHeight = AutoGrid.GetRowHeightOverride(child); if (overrideRowHeight != null) { RowDefinitions[rowIndex].Height = overrideRowHeight.Value; } var overrideColumnWidth = AutoGrid.GetColumnWidthOverride(child); if (overrideColumnWidth != null) { ColumnDefinitions[columnIndex].Width = overrideColumnWidth.Value; } cellPosition += Grid.GetColumnSpan(child); } else { var rowIndex = cellPosition % RowDefinitions.Count; Grid.SetRow(child, rowIndex); var columnIndex = cellPosition / RowDefinitions.Count; Grid.SetColumn(child, columnIndex); var columnSpan = Grid.GetColumnSpan(child); if (columnSpan > 1) { Enumerable.Range(1, columnSpan).ToList() .ForEach(x => cellsToSkip.Enqueue(cellPosition + RowDefinitions.Count * x)); } var overrideRowHeight = AutoGrid.GetRowHeightOverride(child); if (overrideRowHeight != null) { RowDefinitions[rowIndex].Height = overrideRowHeight.Value; } var overrideColumnWidth = AutoGrid.GetColumnWidthOverride(child); if (overrideColumnWidth != null) { ColumnDefinitions[columnIndex].Width = overrideColumnWidth.Value; } cellPosition += Grid.GetRowSpan(child); } } // Set margin and alignment if (ChildMargin != null) { DependencyHelpers.SetIfDefault(child, FrameworkElement.MarginProperty, ChildMargin.Value); } if (ChildHorizontalAlignment != null) { DependencyHelpers.SetIfDefault(child, FrameworkElement.HorizontalAlignmentProperty, ChildHorizontalAlignment.Value); } if (ChildVerticalAlignment != null) { DependencyHelpers.SetIfDefault(child, FrameworkElement.VerticalAlignmentProperty, ChildVerticalAlignment.Value); } } } }
/// <summary> /// Measures the children of a <see cref="T:System.Windows.Controls.Grid" /> in anticipation of arranging them during /// the <see cref="M:ArrangeOverride" /> pass. /// </summary> /// <param name="constraint">Indicates an upper limit size that should not be exceeded.</param> /// <returns> /// <see cref="Size" /> that represents the required size to arrange child content. /// </returns> protected override Size MeasureOverride(Size constraint) { bool isVertical = Orientation == Orientation.Vertical; if (_shouldReindex || (IsAutoIndexing && ((isVertical && _rowOrColumnCount != ColumnDefinitions.Count) || (!isVertical && _rowOrColumnCount != RowDefinitions.Count)))) { _shouldReindex = false; if (IsAutoIndexing) { _rowOrColumnCount = (isVertical) ? ColumnDefinitions.Count : RowDefinitions.Count; if (_rowOrColumnCount == 0) { _rowOrColumnCount = 1; } int cellCount = InternalChildren.Cast <UIElement>().Sum(child => (isVertical) ? GetColumnSpan(child) : GetRowSpan(child)); // Update the number of rows/columns if (isVertical) { int newRowCount = ((cellCount - 1) / _rowOrColumnCount + 1); while (RowDefinitions.Count < newRowCount) { RowDefinitions.Add(new RowDefinition()); } if (RowDefinitions.Count > newRowCount) { RowDefinitions.RemoveRange(newRowCount, RowDefinitions.Count - newRowCount); } } else // horizontal { int newColumnCount = ((cellCount - 1) / _rowOrColumnCount + 1); while (ColumnDefinitions.Count < newColumnCount) { ColumnDefinitions.Add(new ColumnDefinition()); } if (ColumnDefinitions.Count > newColumnCount) { ColumnDefinitions.RemoveRange(newColumnCount, ColumnDefinitions.Count - newColumnCount); } } } // Update children indices int position = 0; foreach (UIElement child in Children) { if (IsAutoIndexing) { if (isVertical) { SetRow(child, position / _rowOrColumnCount); SetColumn(child, position % _rowOrColumnCount); position += GetColumnSpan(child); } else { SetRow(child, position % _rowOrColumnCount); SetColumn(child, position / _rowOrColumnCount); position += GetRowSpan(child); } } // Set margin and alignment if (ChildMargin != null) { child.SetIfDefault(MarginProperty, ChildMargin.Value); } if (ChildHorizontalAlignment != null) { child.SetIfDefault(HorizontalAlignmentProperty, ChildHorizontalAlignment.Value); } if (ChildVerticalAlignment != null) { child.SetIfDefault(VerticalAlignmentProperty, ChildVerticalAlignment.Value); } } } return(base.MeasureOverride(constraint)); }