Control rendering order in UWP Grid using Canvas.ZIndex

WinUI

3 years ago

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:

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:

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:

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:

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.