UWP XAML content alignment brain teaser

I usually find positioning content in XAML more comfortable than in CSS. However, I got stuck with an alignment problem which turned out to have an elegant solution. Let’s look at this brain teaser together!

Consider the following layout:


<Grid>
<Button HorizontalAlignment="Stretch" MaxWidth="250">Example</Button>
</Grid>

We have a stretched button which has a maximum width of 250 . The result looks like this:

UWP button stretched centered

 

What if we now wanted to align the stretched button to the left or the right?

That turns out to be quite challenging. You cannot specify a horizontal alignment like StartAndExpand and EndAndExpand – these options are available in Xamarin.Forms only. Applying HorizontalAlignment in the containing Grid changes the rules completely – it forces the Button to have the minimum possible width it needs, so stretching no longer has the intended effect.

If you want to tackle this brain teaser yourself, take a break from reading here and try it! If you find a different solution than the one presented, please let me know in the comments!

Left alignment

We can move the MaxWidth attribute to a ColumnDefinition in our grid and make the single column * (star) wide:


<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" MaxWidth="250" />
</Grid.ColumnDefinitions>
<Button HorizontalAlignment="Stretch">Example</Button>
</Grid>

The column of the Grid is stretched but has a maximum width of 250 . Columns in Grid start on the left-hand side, so the column is left-aligned as well but the button within it can still stretch.

Left-aligned stretched button

Right alignment

One column is not sufficent for right-alignment, but we can use a very similar trick again with two columns:


<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" MaxWidth="250" />
</Grid.ColumnDefinitions>
<Button HorizontalAlignment="Stretch" Grid.Column="1">Example</Button>
</Grid>

The button will now resides in the second column, which has the same properties as in the previous example. The new first column has * (star) width as well and its purpose is to fill the space remaining after arranging the second column.

This sort of works. Sort of – unless the screen is narrow. In that case, the rule which states that columns of *  width evenly distribute the available width of the Grid takes precedence and both columns have get the same width.

Narrow window evenly distributes Column widths

We need to find another way out. We must trick the Grid into thinking the second column should be significantly wider by default:


<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="10000*" MaxWidth="250" />
</Grid.ColumnDefinitions>
<Button HorizontalAlignment="Stretch" Grid.Column="1">Example</Button>
</Grid>

By giving the second column width of 10000* its width, Grid would by default make the second column 10000 times as wide as the first. Now in combination with MaxWidth it constrains the width to exactly 250 even on narrow screen, and we get precisely the result we wanted:

Right aligned stretched button

In case you found a different solution for this brain teaser I would love to know! Please let me know in the comments ‍🙂💻 .

Buy me a coffeeBuy me a coffee

5 thoughts on “UWP XAML content alignment brain teaser”

  1. I have to be honest.. my immediate thought was ‘that’s not actually difficult – just use columndefinitions and split the grid containing the button up…’
    But I’ve been doing XAML since it came out.. so… 🙂
    Conversely, if you asked me to do something like that with CSS I’d be lost.

  2. Take the left align solution, rotate the grid by 180 to the right and then rotate its content by -180 to the left.

  3. Take the left aligned solution, rotate the grid by 180 to the right and then rotate its content by -180 to the left.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.