0
votes

I want to draw a rectangle on a canvas in WPF. For drawing a line I can do this:

line.X1 = ls.P0.X;
line.Y1 = ls.P0.Y;
line.X2 = ls.P1.X;
line.Y2 = ls.P1.Y;          

MyCanvas.Children.Add(line);

...in other words the location is a property of the line itself. I want to draw a rectangle the same way, i.e., assign its coordinates and add it to my canvas. But the examples I've seen online so far seem to look like this:

rect = new Rectangle
{
    Stroke = Brushes.LightBlue,
    StrokeThickness = 2
};
Canvas.SetLeft(rect,startPoint.X);
Canvas.SetTop(rect,startPoint.X);
canvas.Children.Add(rect);

...in other words it doesn't look like the rectangle has an inherent location, but instead its location is set by calling a method of Canvas. Is this true - Lines have inherent coordinates but Rectangles do not? Is there any way to have a rectangle in WPF with an inherent location, like a line, or do I have to roll my own (using lines)?

2
Use a Path with a RectangleGeometry.Clemens
The examples I've seen online of doing this in C# - creating a path, creating a RectangleGeometry, creating a GeometryGroup, etc, make it look more complicated and overkill than just drawing 4 lines. Is my initial assumption - that lines have inherent location but rectangles don't, correct?user316117

2 Answers

2
votes

You could use a Path control with a RectangleGeometry like this:

var rect = new Path
{
    Data = new RectangleGeometry(new Rect(x, y, width, height)),
    Stroke = Brushes.LightBlue,
    StrokeThickness = 2
};
canvas.Children.Add(rect);
0
votes

...in other words it doesn't look like the rectangle has an inherent location, but instead its location is set by calling a method of Canvas. Is this true - Lines have inherent coordinates but Rectangles do not?

Locations in WPF are relative, which begs the question: coordinates relative to what?

Line, Rectangle, and Path all inherit from Shape, and in the case of any Shape object, the coordinates of the defining geometry are relative to the top-left corner of the Shape itself. Thus, when you create a Line object from (100, 300) to (300, 100), the resulting element is 300x300 points in size, even though the visible line has bounds of 200x200:

Line Diagram

In this case, it is unnecessary to place the Line within a Canvas, as you are not using the coordinate system of the Canvas.

Some shapes like Line and Path allow you to place geometry at any "internal" coordinates you like. Others, like Rectangle and Ellipse, always position their defining geometry at (0, 0) internally, forcing you to use other layout properties to position the shapes within the greater scene (e.g., Canvas.Top/Left, Margin, etc.).

In your example, if you were to define a Rectangle of 200x200 points, and use the Canvas attached properties to position the rectangle at (100, 100), the resulting Rectangle element would measure 200x200, while the parent Canvas would measure itself to be at least 300x300, which is arguably more intuitive:

Diagram 1
(shading added for clarity)

You are correct in that this is rather inconsistent. You may find it useful to always use layout properties (e.g., Canvas.Left/Top) to position shapes within a scene such that all elements are using the same coordinate system.