Zartox29
Zartox29

Reputation: 105

How to draw on a canvas in avalonia?

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

Answers (1)

Tarazed
Tarazed

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

Related Questions