Why is GeometryDrawing displayed on a canvas with cropped coordinates?

I have the following simple code that draws a rectangle

<Canvas Name="MainImageLayer" > <Image > <Image.Source > <DrawingImage xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" > <DrawingImage.Drawing > <DrawingGroup> <DrawingGroup.Children> <GeometryDrawing> <GeometryDrawing.Pen> <Pen Brush="#FF1acc33" Thickness="1" /> </GeometryDrawing.Pen> <GeometryDrawing.Brush> <SolidColorBrush>Red</SolidColorBrush> </GeometryDrawing.Brush> <GeometryDrawing.Geometry> <RectangleGeometry Rect="300,480,287,83" /> </GeometryDrawing.Geometry> </GeometryDrawing> </DrawingGroup.Children> </DrawingGroup> </DrawingImage.Drawing> </DrawingImage> </Image.Source> </Image> </Canvas> 

The result looks like this: note that the rectangle is at (0,0) , even if Rect is defined as

 <RectangleGeometry Rect="300,480,287,83" /> 

enter image description here

I want it to start with (300,480) , for example:

enter image description here

I can achieve this by checking my DrawingImage and doing:

  <Canvas.Top>300</Canvas.Top> <Canvas.Left>480</Canvas.Left> 

But is there a better way, given the fact that this data is encoded in Geometry ?

+4
source share
2 answers

Your problem is that you have all your geometry wrapped in an Image object. By default, the .Height and .Width properties of the Image object are set to "Auto", and the .Stretch property is set to "Uniform". This ensures that your rectangle will always be displayed in the upper left corner of your canvas.

If you really need to encapsulate your geometry in the Image object (which I would warn you not to do), you will need to set the field size of your image object to 300,480,0,0. so that your rectangle appears where you want. This is necessary because of the way the Image object handles its contents.

An Image object does not behave like a Canvas object, even if it is inside it.

If you have some irresistible reason to save the Image object, you will get much better success if you drop the image and draw it directly on the canvas.

EDIT

Why should the Image object not be used in this case?
The image object is mainly used to display ... well, images such as bitmaps, etc. It is not suitable for drawing geometry in it at a specific location (and size). Like most WPF controls, this is what I would call β€œrelative,” which means it's well suited for automatically resizing and positioning with respect to both its content and its parent element. Canvas, on the other hand, is an example of β€œabsolute” control. His whole reason for being is that the content is drawn on it in the exact place with the exact size. Adding an image inside the canvas and then drawing the geometry inside the image simply adds an unnecessary level of complexity between the canvas and the geometry that you want to draw.

How can I add geometry directly?
One of the easiest ways would be to use the Path object specified in Clemens's answer. Just replace the entire Image object and all its contents with 5 lines of this Path, and your rectangle will appear exactly where it should be. You can also do this with a single line and a Rectangle object:

 <Rectangle Height="83" Width="287" Margin="300,480,0,0" Stroke="#FF1acc33" StrokeThickness="1" Fill="Red" /> 

but I would recommend Path, as it contains the size and position of the rectangle in one set of numbers. The path also allows you much more flexibility if you work with shapes other than rectangles.

+6
source

It seems that DrawingImage (or GeometryDrawing?) Is somehow adjusted to its visible rectangle. Anyway, wouldn't it be much easier than Image?

 <Path Stroke="#FF1acc33" StrokeThickness="1" Fill="Red"> <Path.Data> <RectangleGeometry Rect="300,480,287,83" /> </Path.Data> </Path> 

You can also add another non-empty GeometryDrawing that covers (0,0) (for example, RectangeGeometry with Rect = "0,0,1,1") with a transparent brush in the DrawingGroup.

EDIT: As I understand it, DrawingImage is set to Drawing.Bounds

+2
source

Source: https://habr.com/ru/post/1390459/


All Articles