Skip to content

Instantly share code, notes, and snippets.

@jonstodle
Created October 29, 2015 18:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonstodle/7f44a6660031f956f363 to your computer and use it in GitHub Desktop.
Save jonstodle/7f44a6660031f956f363 to your computer and use it in GitHub Desktop.
A panel which arranges as many children as possible into one row and stretches them to uniformly consume the whole width
using System;
using System.Collections.Generic;
using System.Linq;
using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace KodeFisk
{
public class AutoUniformWidthWrapPanel : Panel
{
public AutoUniformWidthWrapPanel()
{
MinimumColumnsOnLastRow = 1;
}
public int MinimumColumnsOnLastRow
{
get { return (int)GetValue(MinimumColumnsOnLastRowProperty); }
set { SetValue(MinimumColumnsOnLastRowProperty, value); }
}
// Using a DependencyProperty as the backing store for MinimumColumnsOnLastRow. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MinimumColumnsOnLastRowProperty =
DependencyProperty.Register("MinimumColumnsOnLastRow", typeof(int), typeof(AutoUniformWidthWrapPanel), new PropertyMetadata(null));
protected override Size MeasureOverride(Size availableSize)
{
var finalSize = new Size { Width = availableSize.Width };
var rowHeight = 0d;
var posX = 0d;
foreach (var child in Children)
{
child.Measure(availableSize);
posX += child.DesiredSize.Width;
if (posX > availableSize.Width)
{
posX = child.DesiredSize.Width;
finalSize.Height += rowHeight;
rowHeight = child.DesiredSize.Height;
}
else
{
rowHeight = Math.Max(child.DesiredSize.Height, rowHeight);
}
}
finalSize.Height += rowHeight;
return finalSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
var posY = 0d;
var currentRow = new List<UIElement>();
var rowHeight = 0d;
foreach (var child in Children)
{
if (currentRow.Sum(x => x.DesiredSize.Width) + child.DesiredSize.Width <= finalSize.Width)
{
currentRow.Add(child);
rowHeight = Math.Max(child.DesiredSize.Height, rowHeight);
}
else
{
var rowChildCount = currentRow.Count;
var columnWidth = finalSize.Width / rowChildCount;
for (int i = 0; i < rowChildCount; i++)
{
currentRow[i].Arrange(new Rect(columnWidth * i, posY, columnWidth, currentRow[i].DesiredSize.Height));
}
posY += rowHeight;
rowHeight = child.DesiredSize.Height;
currentRow = new List<UIElement>();
currentRow.Add(child);
}
}
if (currentRow.Count > 0)
{
var rowChildCount = currentRow.Count;
var columnWidth = finalSize.Width / Math.Max(rowChildCount, MinimumColumnsOnLastRow);
for (int i = 0; i < rowChildCount; i++)
{
currentRow[i].Arrange(new Rect(columnWidth * i, posY, columnWidth, currentRow[i].DesiredSize.Height));
}
}
return finalSize;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment