This is what I had to do to get the functionality I wanted. First I have to create my SquareWrapPanel. This is where the magic happens and arranges my items the way I want.
protected override Size ArrangeOverride(Size finalSize)
{
return ArrangeByChildCount(finalSize);
}
private Size ArrangeByChildCount(Size finalSize)
{
double childWidth = 0;
double childHeight = 0;
foreach (UIElement e in Children)
{
e.Measure(finalSize);
childWidth = e.DesiredSize.Width;
childHeight = e.DesiredSize.Height;
}
if (Children.Count > 0)
{
int square = (int)Math.Sqrt(Children.Count);
int rowCount = square + Children.Count % square;
int columnCount = square;
double height = rowCount * childHeight;
double width = columnCount * childWidth;
Size size = new Size(width, height);
base.ArrangeOverride(size);
return size;
}
else
{
return new Size(300, 300);
}
}
Then I created a custom panel that extended ItemsControl. That way I could bind a collection of items to it. There is nothing in the code behind, but here is the style I had to use.
<Style TargetType="{x:Type local:SquareItemsPanel}" BasedOn="{StaticResource {x:Type ItemsControl}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ItemsControl">
<Border BorderBrush="Black" BorderThickness="2" CornerRadius="4">
<Expander x:Name="exp" Header="View">
<local:SquareWrapPanel IsItemsHost="True"/>
</Expander>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>