using System; using System.ComponentModel; using System.Windows; using System.Windows.Controls; namespace DTS.Common.Controls { public class DynamicGrid : Grid, INotifyPropertyChanged { #region INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged; protected bool SetProperty(ref T storage, T value, string propertyName = null) { if (Equals(storage, value)) return false; storage = value; OnPropertyChanged(propertyName); return true; } protected void OnPropertyChanged(string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } #endregion public DynamicGrid() : base() { Refresh(); } protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved) { base.OnVisualChildrenChanged(visualAdded, visualRemoved); Refresh(); } public void Refresh() { ColumnDefinitions.Clear(); for (byte i = 0; i < GridColumns; i++) { ColumnDefinitions.Add(new ColumnDefinition()); if (i + 1 != GridColumns) { ColumnDefinitions[i].Width = new GridLength(1, GridUnitType.Auto); } else { ColumnDefinitions[i].Width = new GridLength(1, GridUnitType.Star); } } var curRow = 0; var curCol = 0; RowDefinitions.Clear(); if (Children != null) { foreach (UIElement curChild in Children) { if(0 == curCol) { // We're on the first column, we need a new row for the child RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) }); } // Set the child to its row and column SetRow(curChild, curRow); SetColumn(curChild, curCol); // Iderate if (curCol < GridColumns-1) { // We're moving to the next column curCol++; } else { // We're at the end, go back to clumn 0 curCol = 0; curRow++; } } } RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); } private byte _columns = 2; public byte GridColumns { get => _columns; set { _columns = value; Refresh(); } } } }