alzinos alzinos - 1 month ago 19
C# Question

How to draw simple shapes onto a WPF xaml-defined canvas programatically

I am porting (or attempting to) legacy code from a very slow WinForms app to WPF. The WinForms app falls down at the rendering of large images, and it has to rerender very frequently as the user pans around so it has to go.

I have a system in place to draw a canvas in xaml that allows zooming and panning with a custom child of Border, in the xaml it is named imaginatively as "canvas". I am having issues drawing simple ellipses to the canvas from other classes.

namespace ZoomPan
{
public class DisplayManager
{
protected void DrawIcon(Locale locale, Color color)
{
Brush sensorBrush = new SolidColorBrush(color);
Brush sensorOutline = new SolidColorBrush(Colors.Black);
int x = locale.x;
int y = locale.y;
halfSize = 10;
DrawEllipse(locale.Name, sensorBrush, sensorOutline, x - halfSize, y - halfSize, 2 * halfSize, 2 * halfSize);
}

public void DrawEllipse(string name, Brush sensorBrush, Brush sensorPen, int x, int y, int width, int height)
{
double thickness = 5;

Ellipse ellipse = new Ellipse();
/*
Define ellipse
*/
canvas.Children.Add(ellipse);
}
}
}


This was my first attempt, which throws up errors around the final canvas.Children line, namely "The name 'canvas' does not exist in the current context"

I tried moving DrawEllipse to a separate class here, which throws up different errors

namespace ZoomPan
{
public class DisplayManager
{
protected void DrawIcon(Locale locale, Color color)
{
Brush sensorBrush = new SolidColorBrush(color);
Brush sensorOutline = new SolidColorBrush(Colors.Black);
int x = locale.x;
int y = locale.y;
halfSize = 10;
DrawEllipse(locale.Name, sensorBrush, sensorOutline, x - halfSize, y - halfSize, 2 * halfSize, 2 * halfSize);
}
}

public class MainWindow : Window
{
public void DrawEllipse(string name, Brush sensorBrush, Brush sensorPen, int x, int y, int width, int height)
{
double thickness = 5;

Ellipse ellipse = new Ellipse();
/*
Define ellipse
*/
canvas.Children.Add(ellipse);
}
}
}


These errors are around the call to DrawEllipse in the first class:

"The name 'DrawEllipse' does not exist in the current context"

and when I add MainWindow. before the DrawEllipse:

"An object reference is required for the non-static field, method, or property 'ZoomPan.MainWindow.DrawEllipse(string, System.Windows.Media.Brush, System.Windows.Media.Brush, int, int, int, int)'"

When I first played around with WPF, I could get it to display onto the canvas when the DrawEllipse method was inside the public class MainWindow:Window of the MainWindow.xaml.cs file, hence the second attempt above.

I feel I am missing something obvious, and couldn't find any exact dupes of this question on the site.

Answer

The other classes need to be passed the canvas object to be able to use it.

Either pass the canvas to the DisplayManager through the constructor once so it can be stored and then used in all methods:

public class DisplayManager
{
    Canvas canvas;
    public DisplayManager(Canvas canvas)
    {
        this.canvas = canvas;
    }
}

Or pass it into each method each time as the first parameter:

public class DisplayManager
{
    public void DrawEllipse(Canvas canvas, string name, Brush sensorBrush, Brush sensorPen, int x, int y, int width, int height) 
    { 
    }
}
Comments