Я изучаю Avalonia для небольшого проекта, и мне это очень нравится, но я не могу найти много документации по рисованию на холсте.
Моя цель очень проста: нарисовать сетку на холсте...
Однако каждый раз, когда я пытаюсь, ничего не появляется. Несмотря на то, что строки вызываются, когда я размещаю точки останова, я немного теряюсь.
Я создал этот пример, чтобы проиллюстрировать:
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>
В этом примере я вижу красный прямоугольник в верхнем левом углу и бежевый фон, но не сетку. Может кто-нибудь объяснить, почему?
Заранее спасибо и хорошего дня.
Сначала я рассматривал возможность использования элементов Rectangle (потому что это большие линии, верно?), но поскольку мне может понадобиться их много, и они статичны, я думаю, что с линиями может возникнуть та же проблема.
Как упоминал Йерун ван Ланген, ваша проблема в том, что вы рисуете в контексте рисования UserControl. Вы можете использовать линии и добавить их на холст.
Line line = new()
{
// Setup.
};
gridCanvas.Children.Add(line);
Однако помните, что линия — это фигура (Avalonia.Controls.Shapes). Фигуры являются элементами управления, то есть они наследуют Control. Это означает, что у них есть много накладных расходов, которые вам могут не понадобиться, чтобы позволить им функционировать в качестве элемента управления. Это нормально, если вам нужны функции управления, такие как возможность их динамического перемещения, но если все, что вам нужно, это статический рисунок и особенно если в противном случае вам понадобится большое количество фигур, это может потребовать больших затрат ресурсов.
Однако вы можете визуализировать DrawingContext в элементе управления (или в любом визуальном элементе, где рендеринг не запечатан). К сожалению, у нас нет опции DrawingVisual.RenderOpen, такой как WPF, для захвата DrawingContext. Вместо этого вам придется создать класс, производный от Control, и переопределить Render для этого объекта.
public class DrawingCanvas : Control
{
// Constructors and stuff
public override void Render(DrawingContext context)
{
base.Render(context);
// Draw here.
}
}
Вам также может потребоваться вызвать InvalidateVisual()
для рендеринга.
Чтобы включить это в свое представление, просто добавьте локальное пространство имен:
xmlns:local = "clr-namespace=AvaloniaTest"
И добавьте предисловие к имени в xaml:
<local:DrawingCanvas/>
Да, я думаю, что строки - это не то, что мне нужно, к сожалению. Но вторая часть, кажется, то, что мне нужно. Но я создал класс, производный от Canvas, но он помечен как запечатанный, я что-то пропустил?
@Zartox29 Zartox29 Вы абсолютно правы, хорошая новость в том, что вам не нужен Canvas, поэтому вместо этого наследуйте Control. Я обновил свой ответ.
Это именно то, что мне было нужно, спасибо.
Вероятно, это связано с тем, что вы выполняете рендеринг в DrawingContext UserControl, а не в Canvas. Вам следует создать экземпляр класса Line и добавить его на холст
canvas.Children.Add(line);
. Canvas будет обрабатывать события рисования и рисовать всех своих детей. Таким образом, вам не придется рисовать их в событии рисования.