Jaa


Controlling z-order using the ZIndex Property

The Composing a XAML Clip Art Scene posting showed how you could layer multiple drawing objects in an XAML file. The sample XAML file in that posting used the default z-order behavior of objects in a collection. One of the changes made in WPF Beta 2 is the introduction of the ZIndex attached property, which allows you to explicitly set the z-order of objects in the child collection of Panel-derived objects, such as Canvas, Grid, and StackPanel objects.

Using the ZIndex Property
Try running the following code in XAMLPad:

<Canvas Background="Ivory"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation">

  <Canvas>
    <Rectangle Height="60" Width="60" Fill="Gold"/>
    <Rectangle Height="50" Width="70" Fill="Coral"/>
    <Rectangle Height="40" Width="80" Fill="Teal"/>
    <Rectangle Height="30" Width="90" Fill="Black"/>
  </Canvas>

<Canvas Canvas.Left="120">
<Rectangle Canvas.ZIndex="99" Height="60" Width="60" Fill="Gold"/>
<Rectangle Canvas.ZIndex="98" Height="50" Width="70" Fill="Coral"/>
<Rectangle Canvas.ZIndex="97" Height="40" Width="80" Fill="Teal"/>
<Rectangle Canvas.ZIndex="96" Height="30" Width="90" Fill="Black"/>
</Canvas>

</Canvas>

Notice how the second set of Rectangle objects is layered in reverse z-order from the first set of Rectangle objects:

Default and explicit Z-order

The first set of Rectangle objects uses the default z-ordering rendering of objects, which is based on the position of the child object in the Canvas collection -- the first object in the collection is rendered first, then the second object, and so forth. The second set of Rectangle objects uses the ZIndex property to override the default z-ordering of objects in the collection.

In the second set of Rectangle objects, I want to ensure that the first object (the Gold-colored one) is the highest in the z-order, or closest to the foreground.  I have defined its ZIndex value as "99" -- a purely arbitrary value. What is more important is that the value must be greater than any other child object ZIndex value in the Canvas collection. If you do not explicitly set the ZIndex value, it defaults to 0.

You can also set the ZIndex value to a negative value, such as "-99", which places the object even farther from the foreground. ZIndex values are aligned along the z-axis -- higher values are closer to the foreground; lower values are farther from the foreground.

Z-order aligns along the z-axis
Relationship of z-order to z-axis

Accessing the ZIndex Value at Run Time
To retrieve the value of the ZIndex property, use the GetZIndex method of the Panel-derived object:

int zOrder = Canvas.GetZIndex(object);

Likewise, to set the value of the ZIndex property, use the SetZIndex method:

Canvas

.SetZIndex(object, (int)99);

A key performance issue is that changing the ZIndex property of a child object does not change its position within the collection. The ordering within the collection remains the same.

Prior to the introduction of the ZIndex property, you would have had to do the following to change the z-order of objects in a collection:

  1) Remove the child object from the collection.
  2) Re-insert the child object into the collection
      at the desired position.

In short, the addition of the ZIndex property is a much easier and more efficient way to change z-order!

Enjoy,
Lorin

About Us


We are the Windows Presentation Foundation SDK writers and editors.

Comments

  • Anonymous
    July 11, 2007
    Hi, I have a listbox of elements and i want to do a layout transform on one of the elements when it is selected so that it grows bigger than the elements, however it always appears under the item that is added later.  I added in the Property trigger to change the zindex to something like 999999 when IsSelected is true, however this still doesn't work.  Also, is there a way to make elements that are lower in the visual tree appear over elements that are higher?  I'm basically just trying to make a listbox that when you select an item, it grows and will appear over any of the items in the window! Thanks!  Matt

  • Anonymous
    July 11, 2007
    Hi Matt, It sounds like you're doing the right thing. Setting Panel.ZIndex to something non-zero when the item is selected should work. The Panel.ZIndex property defaults to zero, and any larger number will cause that child to be rendered in front of its siblings. If it still doesn't work for you, please feel free to share a small sample that demonstrates the problem here or by emailing wcsdkblg (at) microsoft.com. Thanks!