Canvas
The Canvas panel provides absolute positioning of child elements using Left, Top, Right, and Bottom attached properties.
Namespace
Inheritance
Object → AvaloniaObject → Visual → Layoutable → Control → Panel → Canvas
Attached Properties
Gets or sets the distance from the left edge of the Canvas to the left edge of the child.
Gets or sets the distance from the top edge of the Canvas to the top edge of the child.
Gets or sets the distance from the right edge of the Canvas to the right edge of the child.
Gets or sets the distance from the bottom edge of the Canvas to the bottom edge of the child.
Static Methods
Gets the Left attached property value. Parameters:
element (Control): The element
Returns: The Left value, or double.NaN if not set
Sets the Left attached property value. Parameters:
element (Control): The element
value (double): The Left value
Gets the Top attached property value. Parameters:
element (Control): The element
Returns: The Top value, or double.NaN if not set
Sets the Top attached property value. Parameters:
element (Control): The element
value (double): The Top value
Gets the Right attached property value. Parameters:
element (Control): The element
Returns: The Right value, or double.NaN if not set
Sets the Right attached property value. Parameters:
element (Control): The element
value (double): The Right value
Gets the Bottom attached property value. Parameters:
element (Control): The element
Returns: The Bottom value, or double.NaN if not set
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
Use Canvas only when absolute positioning is needed
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 >
Set explicit Width and Height on children
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