Using a Simple Perfect Squared Square to test UWP controls

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:

Squaring_the_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:

SquareColors

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:

SquareGauges

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:

SquareClocks

Here’s how these three examples look like on a Windows Phone:

SquareColors_Phone SquareGauges_Phone SquareClocks_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!

Advertisements

1 thought on “Using a Simple Perfect Squared Square to test UWP controls

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s