Reputation: 105
I am learning Avalonia for a small project and I really enjoy it, but I can't find much documentation on drawing in a canvas.
My goal is very simple: to draw a grid on my canvas...
However, every time I try, nothing shows up. Even though the lines are being called when I place breakpoints, I am a bit lost.
I created this example to illustrate:
public partial class Tests : UserControl, IInterface
{
private double gridSize = 2;
private SolidColorBrush gridBrush = new SolidColorBrush(Colors.Black);
public Tests()
{
InitializeComponent();
gridCanvas.InvalidateVisual();
}
public override void Render(DrawingContext context)
{
base.Render(context);
DrawGrid(context);
}
private void DrawGrid(DrawingContext context)
{
var canvasWidth = gridCanvas.Bounds.Width;
var canvasHeight = gridCanvas.Bounds.Height;
var pen = new Pen(Brushes.Black, thickness: 20); // Adjust thickness if necessary
for (double x = 0; x < canvasWidth; x += gridSize)
{
context.DrawLine(pen, new Point(x, 0), new Point(x, canvasHeight));
}
for (double y = 0; y < canvasHeight; y += gridSize)
{
context.DrawLine(pen, new Point(0, y), new Point(canvasWidth, y));
}
}
}
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="AvaloniaTest.Tests">
<Canvas Name="gridCanvas" Background="Beige">
<Rectangle Fill="Red" Canvas.Left="10" Canvas.Top="10" Width="5" Height="5"/>
</Canvas>
</UserControl>
In this example, I can see my red rectangle in the top left corner and the beige background, but not the grid. Can someone explain why?
Thanks in advance, and have a nice day.
Upvotes: 1
Views: 766
Reputation: 2675
As mentioned by Jeroen van Langen, your problem is you are drawing to the UserControl drawing context. You could use Lines and add them to the Canvas.
Line line = new()
{
// Setup.
};
gridCanvas.Children.Add(line);
However, Be aware that Line is a Shape (Avalonia.Controls.Shapes). Shapes are controls, that is they inherit Control. This means they have a lot of overhead you may not need in order to allow them to function as a control. This is OK if you need control functionality, such as the ability to move them around dynamically, but if all you need is a static drawing and especially if you would otherwise need a large number of shapes, this can be resource costly.
However, you can render a DrawingContext to a Control (or any visual where the Render isn't sealed). Unfortunately we don't have a DrawingVisual.RenderOpen option like WPF to grab a DrawingContext. Instead you will have to create a class that derives from Control and override Render on that object.
public class DrawingCanvas : Control
{
// Constructors and stuff
public override void Render(DrawingContext context)
{
base.Render(context);
// Draw here.
}
}
You may also need to call InvalidateVisual()
to render.
To include this on your view, just add a local namespace:
xmlns:local="clr-namespace=AvaloniaTest"
And preface the name in xaml:
<local:DrawingCanvas/>
Upvotes: 3