Skip to main content

Canvas

The Canvas panel provides absolute positioning of child elements using Left, Top, Right, and Bottom attached properties.

Namespace

Avalonia.Controls

Inheritance

Object → AvaloniaObject → Visual → Layoutable → Control → Panel → Canvas

Attached Properties

Left
double
Gets or sets the distance from the left edge of the Canvas to the left edge of the child.
Top
double
Gets or sets the distance from the top edge of the Canvas to the top edge of the child.
Right
double
Gets or sets the distance from the right edge of the Canvas to the right edge of the child.
Bottom
double
Gets or sets the distance from the bottom edge of the Canvas to the bottom edge of the child.

Static Methods

GetLeft
double
Gets the Left attached property value.Parameters:
  • element (Control): The element
Returns: The Left value, or double.NaN if not set
SetLeft
void
Sets the Left attached property value.Parameters:
  • element (Control): The element
  • value (double): The Left value
GetTop
double
Gets the Top attached property value.Parameters:
  • element (Control): The element
Returns: The Top value, or double.NaN if not set
SetTop
void
Sets the Top attached property value.Parameters:
  • element (Control): The element
  • value (double): The Top value
GetRight
double
Gets the Right attached property value.Parameters:
  • element (Control): The element
Returns: The Right value, or double.NaN if not set
SetRight
void
Sets the Right attached property value.Parameters:
  • element (Control): The element
  • value (double): The Right value
GetBottom
double
Gets the Bottom attached property value.Parameters:
  • element (Control): The element
Returns: The Bottom value, or double.NaN if not set
SetBottom
void
Sets the Bottom attached property value.Parameters:
  • element (Control): The element
  • value (double): The Bottom value

Usage in XAML

Basic Positioning

<Canvas Width="400" Height="300" Background="WhiteSmoke">
    <!-- Position from top-left -->
    <Rectangle Fill="Red" 
               Width="50" Height="50"
               Canvas.Left="10" Canvas.Top="10" />
    
    <!-- Position from top-left -->
    <Rectangle Fill="Blue" 
               Width="50" Height="50"
               Canvas.Left="100" Canvas.Top="50" />
    
    <!-- Position from top-left -->
    <Rectangle Fill="Green" 
               Width="50" Height="50"
               Canvas.Left="200" Canvas.Top="100" />
</Canvas>

Using Right and Bottom

<Canvas Width="400" Height="300" Background="WhiteSmoke">
    <!-- Top-right corner -->
    <Button Content="Top Right"
            Canvas.Right="10" Canvas.Top="10" />
    
    <!-- Bottom-left corner -->
    <Button Content="Bottom Left"
            Canvas.Left="10" Canvas.Bottom="10" />
    
    <!-- Bottom-right corner -->
    <Button Content="Bottom Right"
            Canvas.Right="10" Canvas.Bottom="10" />
    
    <!-- Centered (using Left and Top at 50%) -->
    <Button Content="Center"
            Canvas.Left="200" Canvas.Top="150" />
</Canvas>

Overlapping Elements

Canvas allows elements to overlap. Control Z-order with ZIndex:
<Canvas Width="300" Height="200" Background="White">
    <!-- Back layer (default ZIndex=0) -->
    <Rectangle Fill="Red" 
               Width="100" Height="100"
               Canvas.Left="50" Canvas.Top="50" />
    
    <!-- Middle layer -->
    <Rectangle Fill="Green" 
               Width="100" Height="100"
               Canvas.Left="80" Canvas.Top="70"
               ZIndex="1" />
    
    <!-- Front layer -->
    <Rectangle Fill="Blue" 
               Width="100" Height="100"
               Canvas.Left="110" Canvas.Top="90"
               ZIndex="2" />
</Canvas>

Drawing Canvas

<Canvas Width="500" Height="400" Background="White">
    <!-- Draw lines -->
    <Line StartPoint="0,0" EndPoint="500,400" 
          Stroke="Black" StrokeThickness="2" />
    <Line StartPoint="500,0" EndPoint="0,400" 
          Stroke="Black" StrokeThickness="2" />
    
    <!-- Draw shapes -->
    <Ellipse Fill="Yellow" Stroke="Black" StrokeThickness="2"
             Width="100" Height="100"
             Canvas.Left="200" Canvas.Top="150" />
    
    <!-- Add text -->
    <TextBlock Text="Canvas Drawing" 
               FontSize="24" FontWeight="Bold"
               Canvas.Left="180" Canvas.Top="190" />
</Canvas>

Code-Behind Usage

Setting Position Programmatically

using Avalonia.Controls;

var canvas = new Canvas();
var button = new Button { Content = "Click Me" };

// Set position using attached properties
Canvas.SetLeft(button, 100);
Canvas.SetTop(button, 50);

canvas.Children.Add(button);

// Get position
var left = Canvas.GetLeft(button);  // Returns 100
var top = Canvas.GetTop(button);    // Returns 50

Animating Position

using Avalonia;
using Avalonia.Animation;
using Avalonia.Controls;
using Avalonia.Media;
using System;

public void AnimateElement(Control element, Point from, Point to)
{
    Canvas.SetLeft(element, from.X);
    Canvas.SetTop(element, from.Y);
    
    var animation = new Animation
    {
        Duration = TimeSpan.FromSeconds(1),
        Children =
        {
            new KeyFrame
            {
                Cue = new Cue(0),
                Setters =
                {
                    new Setter(Canvas.LeftProperty, from.X),
                    new Setter(Canvas.TopProperty, from.Y)
                }
            },
            new KeyFrame
            {
                Cue = new Cue(1),
                Setters =
                {
                    new Setter(Canvas.LeftProperty, to.X),
                    new Setter(Canvas.TopProperty, to.Y)
                }
            }
        }
    };
    
    animation.RunAsync(element);
}

Drag and Drop on Canvas

using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.VisualTree;

public class DraggableCanvas : Canvas
{
    private Control? _draggedElement;
    private Point _dragStartPoint;
    
    protected override void OnPointerPressed(PointerPressedEventArgs e)
    {
        var element = e.Source as Control;
        if (element != null && element != this)
        {
            _draggedElement = element;
            _dragStartPoint = e.GetPosition(this);
            e.Pointer.Capture(element);
        }
        
        base.OnPointerPressed(e);
    }
    
    protected override void OnPointerMoved(PointerEventArgs e)
    {
        if (_draggedElement != null)
        {
            var currentPoint = e.GetPosition(this);
            var delta = currentPoint - _dragStartPoint;
            
            var left = GetLeft(_draggedElement);
            var top = GetTop(_draggedElement);
            
            SetLeft(_draggedElement, 
                double.IsNaN(left) ? delta.X : left + delta.X);
            SetTop(_draggedElement, 
                double.IsNaN(top) ? delta.Y : top + delta.Y);
            
            _dragStartPoint = currentPoint;
        }
        
        base.OnPointerMoved(e);
    }
    
    protected override void OnPointerReleased(PointerReleasedEventArgs e)
    {
        if (_draggedElement != null)
        {
            e.Pointer.Capture(null);
            _draggedElement = null;
        }
        
        base.OnPointerReleased(e);
    }
}

Use Cases

Diagrams and Charts

Precise positioning for custom visualizations

Game UI

Absolute positioning for game elements

Custom Drawing

Arbitrary placement of shapes and lines

Drag & Drop

Interactive element positioning

Best Practices

Canvas doesn’t respond to window resizing. Use Grid or DockPanel for responsive layouts.
<!-- Good: Use Grid for responsive layout -->
<Grid>
    <Button Content="Resizes with window" />
</Grid>

<!-- Use Canvas only for specific needs -->
<Canvas>
    <Button Content="Fixed at 100,50" Canvas.Left="100" Canvas.Top="50" />
</Canvas>
Without explicit sizes, children might not render correctly.
<Canvas>
    <!-- Good: Explicit size -->
    <Rectangle Width="50" Height="50" Fill="Red" 
               Canvas.Left="10" Canvas.Top="10" />
    
    <!-- May not render as expected -->
    <Rectangle Fill="Blue" Canvas.Left="100" Canvas.Top="100" />
</Canvas>
Control which elements appear on top using ZIndex.
<Canvas>
    <Rectangle ZIndex="0" ... />  <!-- Back -->
    <Rectangle ZIndex="1" ... />  <!-- Middle -->
    <Rectangle ZIndex="2" ... />  <!-- Front -->
</Canvas>

See Also

Build docs developers (and LLMs) love