Interop between XAML and the Visual Layer

The Composition APIs empower Universal Windows Platform (UWP) developers to do beautiful and powerful things when they drop down to the Visual Layer (as in the sample below). One of the remarkable things about these APIs is that they are designed, end-to-end, to integrate with the XAML Layer. Because of this built-in interoperability, the Composition APIs allow you to visually enhance your current XAML code without needing to replace it.

This post will cover the specific APIs for pulling Visuals out of your XAML as well as pushing Visuals back into your layout. These are also known as hand-out Visuals and hand-in Visuals. Additionally, we’ll cover some details of property sharing between the Framework Layer and the Visual Layer which you will find helpful to get under your belt. We’ll finish off with a dessert recipe (hint, it includes frosting) that demonstrates how the interop between XAML and the Visual Layer is used to create sweet effects.

Let’s talk about hand-out Visuals

Each XAML UIElement in your page layout has a backing Visual that is used for rendering. Because Visuals can contain other Visuals, the tree made up of Visuals tends to be larger than the logical tree made up of XAML elements. If you have been working with XAML for a while, you are probably already familiar with this concept of visual trees and logical trees.

In fact, grabbing the root backing Visual for your page, rather than a specific element, is a common way to retrieve the current Compositor instance.

// Get the current compositor
Compositor compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;

The Visual you receive from ElementCompositionPreview in this way is referred to as a hand-out Visual. Several properties of a hand-out Visual are effectively shared between your XAML and the Composition API so that changes to UIElement properties — such as those related to position, height and width — can alter the Offset and Size properties of the Visual. Some care should be taken when working with these properties, however. While hand-out Visuals receive property changes made to UIElements, UIElements will not read property changes made to hand-out Visuals. The flow of property information flows in only one direction.

Welcome to Composition Island

The SetElementChildVisual method of ElementCompositionPreview plays the role of equal and opposite reaction to the GetElementVisual method. It allows you to take a Visual you have created and add it to a UIElement’s visual tree. When a Visual is added in this way, it is called a hand-in Visual. It doesn’t participate in property sharing the way hand-out Visuals do. Instead, a hand-in Visual acts as a Composition Island: an isolated piece of Visual-based content surrounded by a sea of XAML.

By default, a hand-in Visual is added as the last member of the UIElement’s visual tree, placing it prominently on top of other child Visuals.

ElementCompositionPreview also has a third method, GetElementChildVisual, which takes a UIElement as an argument and returns the hand-in Visual you previously added to the element’s visual tree.

Things you should know about property sharing and property stomping

As discussed above, property sharing between the Framework Layer and the Visual Layer can be a little tricky if you aren’t careful. The following Visual properties are shared between UIElements and their backing Visuals:

Offset

Size

Opacity

TransformMatrix

Clip

CompositeMode

Size and Offset are especially tricky because, as mentioned before, a UIElement isn’t aware of changes to the property values on the hand-out Visual, even though the hand-out Visual is aware of changes to the UIElement. Consequently, if you change the value of the hand-out Visual’s Offset or Size property and the UIElement’s position changes due to a page resize, the UIElement’s previous position values will stomp all over your hand-out Visual’s values.

There is a simple trick that will allow you to avoid property stomping, though. Place your UIElement inside a Grid control or Border control. Then instead of setting position properties directly on your UIElement, you should set them on the wrapper instead.

By doing this, the UIElement’s position appears to never change from its default settings, and so it doesn’t draw any attention during the layout pass, thus avoiding any unwanted property stomping. Additionally, changes to the hand-out Visual’s Offset property will be relative to the position of the wrapper.

Recipe: How to add frosting to the Visual Layer

In the following recipe, you will add a frosted glass effect to a XAML element that is overlaid on top of an image. This effect illustrates both the GetElementVisual and SetElementChildVisual methods at work. A more detailed example of this recipe can be found in the Dev Center post Visual Layer with XAML.

Let’s start with a simple image control.

While you could add the frosting effect directly to the Image control, placing a canvas over it and then applying a Composition effect to the canvas better demonstrates how smoothly XAML and the Visual Layer work together.

All that remains is to insert the new Visual back into your XAML as a hand-in Visual by using SetElementChildVisual. As a final touch, you can also sync your hand-in Visual with your hand-out Visual.

// Add the blur as a child of the host in the visual tree
ElementCompositionPreview.SetElementChildVisual(FrostHost, frostVisual);
// Make sure size of frost host and frost visual always stay in sync
var bindSizeAnimation = compositor.CreateExpressionAnimation("hostVisual.Size");
bindSizeAnimation.SetReferenceParameter("hostVisual", hostVisual);

The result is a picture half-frosted over by the FrostHost canvas placed on top of it. What’s interesting here is that the frosting was not added to the picture but to a different element. As we would hope, though, the effect passes through to the underlying image without any artifacts or airspace issues.

Wrapping up

The ability to pull hand-out Visuals from your XAML and to insert Composition Islands back into it provides a highly accessible way to go back and forth between the Framework Layer and the Visual Layer. Understanding the central role of the ElementCompositionPreview class is important to accomplishing smooth integration between your XAML and the Composition APIs. If you would like to go even deeper into the Interop story behind Windows.UI.Composition, we highly recommend the following resources.

The Windows team would love to hear your feedback. Please keep the feedback coming using our Windows Developer UserVoice site. If you have a direct bug, please use the Windows Feedback tool built directly into Windows 10.