This article presents a UWP XAML control that displays 21 square UI elements, each of a different size, inside a square.
Math to the rescue
For testing the UI and the performance of some user controls, I wanted to create a square panel to host as many as possible square areas of a different size. That smells like a mathematical problem, right? And yes: I found a mathematical solution in a domain that is called squaring the square.
Allow me to introduce you to the lowest-order simple perfect squared square:
It’s a “squared square” because … well … it’s a square made up of squares. It’s “perfect” because each of the inner squares has a different size, and it’s “simple” because no subset of inner squares forms a rectangle or square. On top of that, all of the 21 inner squares are “integral”: their side is of integer length (which is convenient for calculating coordinates).
You can devote an entire web site to this, or you can use it as a design for furniture. Personally, I think of it as a nice frame for torturing testing UI components.
Creating the Square of Squares control
So I built the SquareOfSquares, a –square- XAML UserControl that hosts a series of –square- ContentControl instances, distributed according to the simples perfect squared square pattern. On the outside, it’s a square Grid, wrapped in a ViewBox. The side of the grid is a multiple of 112, which is the side of the mathematical square. It’s a size in relative pixels, so I made it big enough (1120) to avoid rounding problems when the actual controls are drawn:
<Viewbox Stretch="Uniform"> <Grid x:Name="Root" Height="1120" Width="1120" /> </Viewbox>
The control has a private list of instances of an –also private- InnerSquare class. This list holds the position and the side of all the inner squares:
private List<InnerSquare> GetSquares() { var list = new List<InnerSquare>(); list.Add(new InnerSquare() { Position = new Point(0, 0), Side = 50 }); list.Add(new InnerSquare() { Position = new Point(50, 0), Side = 35 }); list.Add(new InnerSquare() { Position = new Point(85, 0), Side = 27 }); // more of these ... return list; }
When the SquareOfSquare is created, 112 rows and columns are created, and for each of the inner squares a ContentControl is created with the relevant attached grid properties (i.e. row, column, and both spans):
for (int i = 0; i < 112; i++) { Root.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) }); Root.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) }); } foreach (InnerSquare square in GetSquares()) { var ctl = new ContentControl(); ctl.SetValue(Grid.RowProperty, square.Position.Y); ctl.SetValue(Grid.ColumnProperty, square.Position.X); ctl.SetValue(Grid.ColumnSpanProperty, square.Side); ctl.SetValue(Grid.RowSpanProperty, square.Side); Root.Children.Add(ctl); Squares.Add(ctl); }
The content controls are added to the grid, but also to a Squares list, which is exposed as a property:
public List<ContentControl> Squares { get; private set; } = new List<ContentControl>();
I also added some extension methods that apply to the inner squares: Side() and RandomColor():
private static Random r = new Random(DateTime.Now.Millisecond); /// <summary> /// Returns the side of an inner square. /// </summary> public static int Side(this UIElement element) { return (int)element.GetValue(Grid.RowSpanProperty); } /// <summary> /// Returns a random color. /// </summary> /// <remarks>Not necessarily an extension method. Just for convenience.</remarks> public static Color RandomColor(this UIElement element) { byte red = (byte)r.Next(0, 255); byte green = (byte)r.Next(0, 255); byte blue = (byte)r.Next(0, 255); return new Color() { A = 255, R = red, G = green, B = blue }; }
Feel free to add similar methods to return the position of the square, if you require.
Using the Square of Squares control
To use the control, drop it on a page, and give it a name:
<controls:SquareOfSquares x:Name="SquareOfSquares" Margin="20" />
To populate the inner squares, iterate through the Squares collection, create your UI element, and set it as Content of the inner square. The following code snippet creates a grid with a random background color, that displays the length of the side of the square in its upper left corner:
foreach (var square in SquareOfSquares.Squares) { var grid = new Grid() { Height = square.ActualHeight, Width = square.ActualWidth }; grid.Background = new SolidColorBrush(square.RandomColor()); var side = square.Side().ToString(); grid.Children.Add(new TextBlock() { Text = side, Margin = new Thickness(2.0, 1.0, 0.0, 0.0), Foreground = new SolidColorBrush(Colors.White) }); square.Content = grid; }
Here’s how that looks like:
Here’s the code to add a Radial Gauge control (from NuGet) to each of the squares:
foreach (var square in SquareOfSquares.Squares) { var gauge = new Gauge() { Height = square.ActualHeight, Width = square.ActualWidth }; gauge.TrailBrush = new SolidColorBrush(square.RandomColor()); gauge.TickBrush = new SolidColorBrush(Colors.Transparent); gauge.ScaleTickBrush = new SolidColorBrush(Colors.LemonChiffon); gauge.NeedleBrush = new SolidColorBrush(Colors.OrangeRed); gauge.Maximum = 50; var side = square.Side(); gauge.Value = side; square.Content = gauge; }
This is the result:
And here’s the very straightforward code to add a Composition API Clock control:
foreach (var square in SquareOfSquares.Squares) { var clock = new Clock() { Height = square.ActualHeight, Width = square.ActualWidth }; square.Content = clock; }
This code results in a simple perfect squared square of ticking clocks:
Here’s how these three examples look like on a Windows Phone:
![]() |
![]() |
![]() |
Source Code
The sample app, together with the SquareOfSquares control, lives here on GitHub. The control is in its own project, ready for use.
Enjoy!
Cool! 🙂
LikeLike