Control rendering order in UWP Grid using Canvas.ZIndex

Canvas is a useful to implement absolute positioning of UI elements and provides a ZIndex property to define their rendering order as well. However, sometimes such a property would be useful in other Panels as well.

For example, consider a Grid as follows:

<Grid>
<TextBlock Text="This is a title" Style="{ThemeResource TitleTextBlockStyle}" />
<Image Source="/Assets/Background.jpg" Stretch="UniformToFill" />
</Grid>

view raw
GridWithoutZIndex.cs
hosted with ❤ by GitHub

Although it is natural from the logical standpoint to have the title TextBlock as the first child of the Grid, the result will be the following:

The title text is nowhere to be seen

The title text is nowhere to be seen! The reason for that is the Image is stretching across the whole Grid and as it is rendered second, it covers the TextBlock.  Usually, this is when we switch the order of children:

<Grid>
<Image Source="/Assets/Background.jpg" Stretch="UniformToFill" />
<TextBlock Text="This is a title" Style="{ThemeResource TitleTextBlockStyle}" />
</Grid>

This works well. The title text is rendered after the image, so it is above it. However, this benefit brought one disadvantage – the “reading order” of the code is mixed up.

Luckily, this is where Canvas.ZIndex comes in. Surprisingly, this attached dependency property does not apply only to Canvas, but also to other Panel derived classes, including Grid. Let’s see what happens when we do this:

<Grid>
<TextBlock Text="This is a title" Style="{ThemeResource TitleTextBlockStyle}" Canvas.ZIndex="10" />
<Image Source="/Assets/Background.jpg" Stretch="UniformToFill" />
</Grid>

view raw
GridWithZIndex.cs
hosted with ❤ by GitHub

We set the Canvas.ZIndex attached property on our TextBlock to 10. The result now looks just as we expect:

Here is our title above the image

Although the TextBlock is the first child of the Grid, thanks to its positive Canvas.ZIndex value, it now renders above the “background” image. The Canvas.ZIndex property can be used in any Panel-derived class to adjust the rendering order. The default value is zero, and higher value means the control is rendered later. Finally, when two control’s ZIndex value is tied, the XAML-declaration order determines the rendering order.

Personally, I didn’t know about this trick until I saw the template of WinUI NavigationView control, which uses it to render the navigation pane button grid above the content (see here on GitHub), while preserving the “logical” reading order of XAML. Very cool!

What about WPF?

In WPF, the ZIndex property is declared directly on the Panel class, which actually makes the trick clearer:

<Grid>
<TextBlock Text="This is a title" Panel.ZIndex="10" />
<Image Source="/Assets/Background.jpg" Stretch="UniformToFill" />
</Grid>

view raw
GridWithZIndexWpf.cs
hosted with ❤ by GitHub

What about Uno Platform?

Currently, the ZIndex property is not yet supported in non-Canvas panels. However, there is an open issue for this already – Add support for Canvas.ZIndex in any Panel · Issue #325. If you would like to see this supported, vote on this issue and it will surely be addressed soon!

Source code

Sample source code for this article is available on my GitHub.

 

Buy me a coffeeBuy me a coffee

1 thought on “Control rendering order in UWP Grid using Canvas.ZIndex”

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.