using System; namespace Avalonia.Controls.Primitives { /// /// A with uniform column and row sizes. /// public class UniformGrid : Panel { /// /// Defines the property. /// public static readonly StyledProperty RowsProperty = AvaloniaProperty.Register(nameof(Rows)); /// /// Defines the property. /// public static readonly StyledProperty ColumnsProperty = AvaloniaProperty.Register(nameof(Columns)); /// /// Defines the property. /// public static readonly StyledProperty FirstColumnProperty = AvaloniaProperty.Register(nameof(FirstColumn)); private int _rows; private int _columns; /// /// Specifies the row count. If set to 0, row count will be calculated automatically. /// public int Rows { get => GetValue(RowsProperty); set => SetValue(RowsProperty, value); } /// /// Specifies the column count. If set to 0, column count will be calculated automatically. /// public int Columns { get => GetValue(ColumnsProperty); set => SetValue(ColumnsProperty, value); } /// /// Specifies, for the first row, the column where the items should start. /// public int FirstColumn { get => GetValue(FirstColumnProperty); set => SetValue(FirstColumnProperty, value); } protected override Size MeasureOverride(Size availableSize) { UpdateRowsAndColumns(); var maxWidth = 0d; var maxHeight = 0d; var childAvailableSize = new Size(availableSize.Width / _columns, availableSize.Height / _rows); foreach (var child in Children) { child.Measure(childAvailableSize); if (child.DesiredSize.Width > maxWidth) { maxWidth = child.DesiredSize.Width; } if (child.DesiredSize.Height > maxHeight) { maxHeight = child.DesiredSize.Height; } } return new Size(maxWidth * _columns, maxHeight * _rows); } protected override Size ArrangeOverride(Size finalSize) { var x = FirstColumn; var y = 0; var width = finalSize.Width / _columns; var height = finalSize.Height / _rows; foreach (var child in Children) { if (!child.IsVisible) { continue; } child.Arrange(new Rect(x * width, y * height, width, height)); x++; if (x >= _columns) { x = 0; y++; } } return finalSize; } private void UpdateRowsAndColumns() { _rows = Rows; _columns = Columns; if (FirstColumn >= Columns) { FirstColumn = 0; } var itemCount = FirstColumn; foreach (var child in Children) { if (child.IsVisible) { itemCount++; } } if (_rows == 0) { if (_columns == 0) { _rows = _columns = (int)Math.Ceiling(Math.Sqrt(itemCount)); } else { _rows = Math.DivRem(itemCount, _columns, out int rem); if (rem != 0) { _rows++; } } } else if (_columns == 0) { _columns = Math.DivRem(itemCount, _rows, out int rem); if (rem != 0) { _columns++; } } } } }