1

I have to build aerodynamically a canvas with different rectangles and some of them has to be crossed. I do this by adding 2 lines as diagonals of the rectangle. The problem is when i set the line to be thicker, the line will go over the rectangle contour like in the picture: enter image description here

Is there a way to set the line to be only inside the rectangle?

Here is the code that i am using to add a rectangle and the lines:

private void DrawRectangle()
    {
        var rectangle = new Rectangle();
        rectangle.Height = 100;
        rectangle.Width = 100;
        rectangle.Fill = Brushes.Yellow;
        rectangle.Stroke = System.Windows.Media.Brushes.Blue;
        rectangle.StrokeThickness = 1;

        _canvas.Children.Add(rectangle);
    }

    private void DrawBroken(Rectangle rectangle, long left, long bottom)
    {
        DrawBrokenLine(0, 0, 100, 100);
        DrawBrokenLine(0, 100, 100, 0);
    }

    private void DrawBrokenLine(long x1, long y1, long x2, long y2)
    {
        var line = new Line();
        line.X1 = x1;
        line.Y1 = y1;
        line.X2 = x2;
        line.Y2 = y2;
        line.Stroke = Brushes.Indigo;
        line.StrokeThickness = 10;

        _canvas.Children.Add(line);
    }
Andrea Perelli
  • 156
  • 2
  • 3
  • 14
XamWaZZ
  • 59
  • 2
  • 12

3 Answers3

2

You may add the Rectangle and the Lines to another Canvas that clips its child elements:

<Canvas Width="100" Height="100" ClipToBounds="True">
   <Rectangle Width="100" Height="100" Fill="Yellow" Stroke="Blue" StrokeThickness="1"/>
   <Line X1="0" Y1="0" X2="100" Y2="100" Stroke="Indigo" StrokeThickness="10"/>
   <Line X1="0" Y1="100" X2="100" Y2="0" Stroke="Indigo" StrokeThickness="10"/>
</Canvas>
Clemens
  • 123,504
  • 12
  • 155
  • 268
  • And what if i will have a lot of rectangles in my original canvas? I will not have performance issues or something if i am using more canvas? Also i will draw text on the canvas and right now to set the right coordinates where i am adding the rectangles or text i am using Canvas.SetTop() that is a static method. How will this work when i will have more canvases? – XamWaZZ Jul 18 '18 at 08:36
  • "I will not have performance issues or something if i am using more canvas?" No, you won't. For adding text elements, use coordinates relative to the inner Canvas. – Clemens Jul 18 '18 at 08:39
0

You can use a DrawingBrush and set the Shape Background property to that.

<Rectangle Width="100" Height="100" Stroke="Black" StrokeThickness="1">
  <Rectangle.Fill>
    <DrawingBrush >
      <DrawingBrush.Drawing>                
        <GeometryDrawing Geometry="M0,0 L1,1 M1,0 L0,1"
          Stroke="Purple" StrokeThickness="10"/>                    
       </DrawingBrush.Drawing>
     </DrawingBrush>
   </Rectangle.Fill>
 </Rectangle>

UPDATE:

There is an example in this page, demonstrating how to use DrawingBrush programmatically:

// Create a DrawingBrush.
DrawingBrush myDrawingBrush = new DrawingBrush();

// Create a drawing.
GeometryDrawing myGeometryDrawing = new GeometryDrawing();
myGeometryDrawing.Brush = Brushes.LightBlue;
myGeometryDrawing.Pen = new Pen(Brushes.Gray, 1);
GeometryGroup ellipses = new GeometryGroup();
ellipses.Children.Add(new EllipseGeometry(new Point(25,50), 12.5, 25));
ellipses.Children.Add(new EllipseGeometry(new Point(50,50), 12.5, 25));
ellipses.Children.Add(new EllipseGeometry(new Point(75,50), 12.5, 25));

myGeometryDrawing.Geometry = ellipses;
myDrawingBrush.Drawing = myGeometryDrawing;

Button myButton = new Button();
myButton.Content = "A Button";

// Use the DrawingBrush to paint the button's background.
myButton.Background = myDrawingBrush;

You don't need to do the same things, but the idea is that you create a Drawing (the two diagonal lines you desire, which can be a GeometryDrawing), and create a DrawingBrush from that, that you can use in your Rectangle.

heltonbiker
  • 26,657
  • 28
  • 137
  • 252
  • Can you give me an example please? – XamWaZZ Jul 18 '18 at 08:34
  • And how can i generate it programmatically? – XamWaZZ Jul 25 '18 at 13:05
  • For every XAML line of code, there is an equivalent C# way of getting the same thing. From your original code, you have to set the `Fill` of the Rectangle with an object that you have to create, and this object is a `DrawingBrush`. – heltonbiker Jul 25 '18 at 14:10
0

If you don't like the squared ends of the lines you can set their end caps.

<Line X1="0" Y1="0" X2="100" Y2="100" Stroke="Indigo" StrokeThickness="10" StrokeEndLineCap="Triangle" StrokeStartLineCap="Triangle"/>
<Line X1="0" Y1="100" X2="100" Y2="0" Stroke="Indigo" StrokeThickness="10" StrokeEndLineCap="Triangle" StrokeStartLineCap="Triangle"/>

Also, keep in mind with a StrokeThickness of 10, the lines will be drawn past the start and end coordinates so you may need to adjust accordingly (unless you clip like another person suggested). Adding 4 to the starts (0 => 4) and subtracting 4 from the ends (100 => 96) seems about right.

Jeff R.
  • 1,493
  • 1
  • 10
  • 14