Primary APIs:
ElementComposition.GetElementVisual(...)ElementComposition.SetElementChildVisual(...)CompositorCompositionObject.StartAnimation(...)CompositionObject.StopAnimation(...)CompositionAnimationGroupImplicitAnimationCollectionCompositionCustomVisualCompositionCustomVisualHandlerCompositor.RequestCompositionUpdate(...)Compositor.RequestCommitAsync()Reference source files:
src/Avalonia.Base/Rendering/Composition/ElementCompositionPreview.cssrc/Avalonia.Base/Rendering/Composition/Compositor.cssrc/Avalonia.Base/Rendering/Composition/Compositor.Factories.cssrc/Avalonia.Base/Rendering/Composition/CompositionObject.cssrc/Avalonia.Base/Rendering/Composition/CompositionCustomVisualHandler.cssamples/ControlCatalog/Pages/CompositionPage.axaml.cssamples/ControlCatalog/Pages/OpenGl/OpenGlLeasePage.xaml.csGet the composition visual backing a normal Avalonia visual:
var compositionVisual = ElementComposition.GetElementVisual(myControl);
Attach a custom child composition visual:
var compositor = ElementComposition.GetElementVisual(myControl)!.Compositor;
var child = compositor.CreateSolidColorVisual();
ElementComposition.SetElementChildVisual(myControl, child);
Important constraint:
Compositor instance.Common factories on Compositor:
CreateContainerVisual()CreateSolidColorVisual()CreateSurfaceVisual()CreateCustomVisual(handler)CreateExpressionAnimation(...)CreateAnimationGroup()CreateImplicitAnimationCollection()Core pattern:
Target to property name.StartAnimation.var visual = compositor.CreateSolidColorVisual();
var color = compositor.CreateColorKeyFrameAnimation();
color.Target = "Color";
color.InsertKeyFrame(0f, Colors.Red);
color.InsertKeyFrame(1f, Colors.Blue);
color.Duration = TimeSpan.FromSeconds(1);
color.IterationBehavior = AnimationIterationBehavior.Forever;
visual.StartAnimation("Color", color);
Use implicit animations for automatic transitions on property change:
var implicitAnimations = compositor.CreateImplicitAnimationCollection();
implicitAnimations["Offset"] = compositor.CreateAnimationGroup();
compositionVisual.ImplicitAnimations = implicitAnimations;
Use CompositionCustomVisualHandler for custom render-thread visual logic.
Key overridable methods:
OnRender(ImmediateDrawingContext drawingContext)OnMessage(object message)OnAnimationFrameUpdate()Useful protected methods:
Invalidate() / Invalidate(Rect)RegisterForNextAnimationFrameUpdate()GetRenderBounds()RenderClipContains(...)RenderClipIntersectes(...)The sample in CompositionPage and OpenGlLeasePage demonstrates this pattern.
Two major mechanisms:
RegisterForNextAnimationFrameUpdate() inside custom visual handlerCompositor.RequestCompositionUpdate(Action) for UI-thread pre-commit updatesUse Compositor.RequestCommitAsync() when you need explicit commit lifecycle control.
Target string or property unsupported for that object type.OnRender not called:
SetElementChildVisual.SetElementChildVisual(host, null) on detach.Default mode:
XAML-first references:
.axamlXAML-first usage example:
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MyApp.Views.CompositionView">
<Border x:Name="CompositionHost"
Width="320"
Height="180"
Background="#1E1E1E" />
</UserControl>
Code-only alternative (on request):
var host = this.FindControl<Border>("CompositionHost")!;
var visual = ElementComposition.GetElementVisual(host)!;
var compositor = visual.Compositor;
var child = compositor.CreateSolidColorVisual();
ElementComposition.SetElementChildVisual(host, child);