Created
October 6, 2017 15:58
-
-
Save t00/e6580f260e56d09a529c53db38437cc1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.Linq; | |
| using System.Windows; | |
| using System.Windows.Controls; | |
| namespace Custom.Controls | |
| { | |
| public class ColumnPanel: Panel | |
| { | |
| public static readonly DependencyProperty ColumnsProperty = DependencyProperty.Register | |
| ( | |
| "Columns", | |
| typeof(int), | |
| typeof(ColumnPanel), | |
| new FrameworkPropertyMetadata(2, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure) | |
| ); | |
| /// <summary> | |
| /// Gets or sets the number of columns in which controls will be arranged | |
| /// </summary> | |
| public int Columns | |
| { | |
| get { return (int)GetValue(ColumnsProperty); } | |
| set { SetValue(ColumnsProperty, value); } | |
| } | |
| public static readonly DependencyProperty RowSpacingProperty = DependencyProperty.Register | |
| ( | |
| "RowSpacing", | |
| typeof(double), | |
| typeof(ColumnPanel), | |
| new FrameworkPropertyMetadata(0.0d, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure) | |
| ); | |
| /// <summary> | |
| /// Gets or sets the amount of spacing (in device independent pixels) between the rows. | |
| /// </summary> | |
| public double RowSpacing | |
| { | |
| get { return (double)GetValue(RowSpacingProperty); } | |
| set { SetValue(RowSpacingProperty, value); } | |
| } | |
| public static readonly DependencyProperty ColumnSpacingProperty = DependencyProperty.Register | |
| ( | |
| "ColumnSpacing", | |
| typeof(double), | |
| typeof(ColumnPanel), | |
| new FrameworkPropertyMetadata(0.0d, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure) | |
| ); | |
| /// <summary> | |
| /// Gets or sets the amount of spacing (in device independent pixels) between the columns. | |
| /// </summary> | |
| public double ColumnSpacing | |
| { | |
| get { return (double)GetValue(ColumnSpacingProperty); } | |
| set { SetValue(ColumnSpacingProperty, value); } | |
| } | |
| public static readonly DependencyProperty StretchColumnProperty = DependencyProperty.Register | |
| ( | |
| "StretchColumn", | |
| typeof(int), | |
| typeof(ColumnPanel), | |
| new FrameworkPropertyMetadata(1, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure) | |
| ); | |
| /// <summary> | |
| /// Gets or sets the number of columns in which controls will be arranged | |
| /// This is 0-based index of a column, by default set to 1 (second column) | |
| /// </summary> | |
| public int StretchColumn | |
| { | |
| get { return (int)GetValue(StretchColumnProperty); } | |
| set { SetValue(StretchColumnProperty, value); } | |
| } | |
| protected override Size MeasureOverride(Size constraint) | |
| { | |
| double widthSoFar = 0; | |
| columnWidths.Clear(); | |
| rowHeights.Clear(); | |
| for(var column = 0; column < Columns; column++) | |
| { | |
| var widthRemaining = Math.Max(0, constraint.Width - widthSoFar); | |
| var columnConstraint = new Size(widthRemaining, constraint.Height); | |
| double columnWidth = 0; | |
| for(var i = column; i < VisualChildrenCount; i += Columns) | |
| { | |
| if(i < Children.Count) | |
| { | |
| var child = Children[i]; | |
| child.Measure(columnConstraint); | |
| columnWidth = Math.Max(child.DesiredSize.Width, columnWidth); | |
| if(column == 0) | |
| { | |
| rowHeights.Add(child.DesiredSize.Height); | |
| } | |
| else | |
| { | |
| rowHeights[i/Columns] = Math.Max(rowHeights[i/Columns], child.DesiredSize.Height); | |
| } | |
| } | |
| } | |
| columnWidths.Add(columnWidth); | |
| widthSoFar += columnWidth + ColumnSpacing; | |
| } | |
| return new Size(Math.Max(0, widthSoFar - ColumnSpacing), Math.Max(0, rowHeights.Sum() + ((rowHeights.Count - 1) * RowSpacing))); | |
| } | |
| protected override Size ArrangeOverride(Size arrangeSize) | |
| { | |
| double x = 0; | |
| double y = 0; | |
| for(var i = 0; i < VisualChildrenCount; i++) | |
| { | |
| var child = Children[i]; | |
| var column = i % Columns; | |
| var isLastColumn = column == Columns - 1; | |
| var height = rowHeights[i / Columns]; | |
| var width = columnWidths[column]; | |
| if(column == StretchColumn) | |
| { | |
| width = Math.Max(width, arrangeSize.Width - columnWidths.Sum() + width - (ColumnSpacing * (Columns - 1))); | |
| } | |
| if(column == 0) | |
| { | |
| x = 0; | |
| } | |
| var r = new Rect(x, y, width, height); | |
| child.Arrange(r); | |
| x += width + ColumnSpacing; | |
| if(isLastColumn) | |
| { | |
| y += height + RowSpacing; | |
| } | |
| } | |
| return base.ArrangeOverride(arrangeSize); | |
| } | |
| private readonly List<double> columnWidths = new List<double>(); | |
| private readonly List<double> rowHeights = new List<double>(); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment