Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF drawing that stretches without stretching the Pen

I need to draw some simple lines within a Border control (or similar) that always stretch to the bounds of the Border. Is there a way to stretch the lines only but not its pen? Without involving lots of C#?

In this version the lines stretch:

<Border>
   <Border.Background>
      <DrawingBrush>
         <DrawingBrush.Drawing>
            <DrawingGroup>
               <GeometryDrawing Brush="Red">
                  <GeometryDrawing.Geometry>
                     <GeometryGroup>
                        <RectangleGeometry Rect="0,0 100,1000" />
                        <LineGeometry  StartPoint="0,0" EndPoint="100,1000"/>
                        <LineGeometry  StartPoint="100,0" EndPoint="0,1000"/>
                     </GeometryGroup>
                  </GeometryDrawing.Geometry>
                  <GeometryDrawing.Pen>
                     <Pen Thickness="20" Brush="Black"/>
                  </GeometryDrawing.Pen>
               </GeometryDrawing>
            </DrawingGroup>
         </DrawingBrush.Drawing>
      </DrawingBrush>
   </Border.Background>
</Border>

The best solution I have come up with is this:

<Border>
   <Grid>
      <Path Stretch="Fill" Fill="Red" Stroke="Black" StrokeThickness="4"  Data="M0,0 L100,0 100,1000 0,1000 z" />
      <Path Stretch="Fill" Stroke="Black" StrokeThickness="4"  Data="M 0,0 L0,0 100,1000" />
      <Path Stretch="Fill" Stroke="Black" StrokeThickness="4"  Data="M 100,0 L100,0 0,1000" />
   </Grid>
</Border>

But isn't there a better solution? That doesn't involve extra Grid?

like image 990
bitbonk Avatar asked Aug 26 '09 21:08

bitbonk


3 Answers

I've done this by scaling a Path's Data, not the visual component.

  1. Place a Path in a Canvas.
  2. Set path.Data to a Geometry representing your data as percentages of the logical range.
  3. Set path.Data.Transform to a ScaleTransform with ScaleX and ScaleY bound to the actual width and height.
like image 149
Shawn Hoover Avatar answered Nov 15 '22 08:11

Shawn Hoover


Within a line, you can bind the width (or height, depending on which way you are drawing the line) to that of the parent container to achieve what you want.

    <Grid x:Name="Grid" Margin="10">
        <Border BorderBrush="Black" BorderThickness="1"  />
        <Line X1="0" X2="{Binding ElementName=Grid, Path=ActualWidth}" Y1="1" Y2="1" Stroke="Red" Margin="0,10,0,0" />
        <Line X1="0" X2="{Binding ElementName=Grid, Path=ActualWidth}" Y1="1" Y2="1" Stroke="Green" Margin="0,30,0,0" />
        <Line X1="0" X2="{Binding ElementName=Grid, Path=ActualWidth}" Y1="1" Y2="1" Stroke="Blue" Margin="0,50,0,0" />
    </Grid>

Edit: Here is another way without using binding

<Border BorderBrush="Black" BorderThickness="1" >
    <Path Stroke="Red" StrokeThickness="1" Data="M0,0 1,0Z" Stretch="Fill" />
</Border>
like image 44
mdm20 Avatar answered Nov 15 '22 07:11

mdm20


None that I know of. But unless you're doing something really extravagant, it really isn't a lot of effort to override OnRender and draw it yourself:

public class CustomBorder : Border
{
    protected override void OnRender(DrawingContext dc)
    {
        base.OnRender(dc);

        dc.DrawLine(new Pen(BorderBrush, BorderThickness.Top), new Point(0, 0), new Point(ActualWidth, ActualHeight));
    }
}

Result:

enter image description here

like image 26
Kent Boogaart Avatar answered Nov 15 '22 07:11

Kent Boogaart