18

I have a Path that must resize to its StackPanel container.

<StackPanel x:Name="TrackSurface">
    <Path Fill="AliceBlue"
          Stroke="Black" StrokeThickness="1"
          Data="{StaticResource TranslateZ}">
    </Path>
</StackPanel>

I think about using a transformation bound to the container but don't know how to it actually. Can someone give me hint?

Tetsujin no Oni
  • 7,300
  • 2
  • 29
  • 46
742
  • 3,009
  • 3
  • 23
  • 18

4 Answers4

33

I changed the Stackpanel to Grid and Stretch property of the Path to Fill.

<Grid x:Name="TrackSurface"> 
<Path Fill="AliceBlue" 
Stretch="Fill"
      Stroke="Black" StrokeThickness="1" 
      Data="M148,28 C221,133 110.50025,119.5 110.50025,119.5 L124.50016,68.5 z"> 
</Path> 

Kishore Kumar
  • 21,449
  • 13
  • 81
  • 113
  • Thanks Kishore. It doesn't work in my case. I have a Grid with a UserControl in a row, the Path is in the UserControl. It must not extend the column width. This is why I used a StackPanel. I've overriden OnRenderSizeChanged in the UserControl to maintain an aspect ratio of 1. So the Path needs to fill a squared UserControl which size is the column width. Not sure I'm clear. With your solution, the column width extend to match the original bouding box of the Path. – 742 May 05 '10 at 10:39
  • 2
    @742, did you see my answer below? Why not just use a ViewBox? (Ok, so this is three years old, but someone just voted up my answer which brought me back here.) – Mark A. Donohoe Oct 01 '13 at 17:59
  • Just adding more info. This way works, but is limited because you're forcing the path to stretch to fill its container, which may not always be the case. Think about the symbol for females... a circle with a cross at the bottom. If your path has its spacing laid out that you want the center of the circle to be in the center of the display area, your path has to have coordinates that are relative to its container. Set the container (Grid) to the size of the extents, then place the path in it. (Continued below...) – Mark A. Donohoe Feb 24 '16 at 17:45
  • It will appear as expected but at the size of the design. You then simply put the grid in the ViewBox and everything will be properly scaled without the artifacts caused by filling the container (since you are actually filling, but now you're filling the grid to the viewbox.) That's what a ViewBox does... essentially lets you scale any content while (optionally) maintaining positional and aspect relevance inside. It's pretty cool stuff! – Mark A. Donohoe Feb 24 '16 at 17:47
23

Any reason why you're not using a ViewBox for this? That will shrink or grow the path as needed. If you don't want it scaled, but rather clipped, then set the clipping mode to be restricted to the control's bounding box. (I'd wrap the path in a ContentPresenter for that.)

Mark A. Donohoe
  • 28,442
  • 25
  • 137
  • 286
  • 1
    This is old, but it is still the better answer. All I had to do was wrap my `Path`s in a `Grid` inside a `ViewBox`, and everything was perfect. – moswald Jul 15 '15 at 17:26
  • Create a `Grid`, add a `ViewBox` child, assign `ViewBox` to desired `Grid` coordinates, and finally add your `Path` as a child to the `ViewBox`. – Xaero Degreaz Jun 03 '18 at 04:54
  • 1
    Xaero, I actually think it's the other way around. Put the grid in the viewbox. That's because you want your path's coordinates to be respected, which is where the grid comes in. Yes, you could use margins, etc., but the grid is cleaner. Then you put *that* grid in the ViewBox which should be considered only for scaling purposes, not positioning. More broadly, it's for *VIEW*ing the properly-laid-out controls, and that's why the grid should be inside. Technically both ways will work, but one will save you a lot of headaches and be easier for others to follow. – Mark A. Donohoe Jun 12 '18 at 12:57
4

Ensure that your path is smaller than your StackPanel.

Easiest way for a very easy path will be to move the comma in every number (i.e. divide everything by 10 or 100 in TranslateZ), or for more complicated paths add a LayoutTransform (lower the scaling factor as needed):

<StackPanel x:Name="TrackSurface">
    <Path Fill="AliceBlue" Stroke="Black" StrokeThickness="1" 
          Data="{StaticResource TranslateZ}">
          <Path.LayoutTransform>
               <ScaleTransform ScaleX="0.1" ScaleY="0.1"/>
          </Path.LayoutTransform>
    </Path>
</StackPanel>

Some Remarks:

I had a similar problem, with a button template containing a path. The button's "auto" size was determined by the path, because the path had the largest dimensions of the template content.

This in itself might not turn out as a problem, because if you specify the button's height/width, or if the button's Horizontal-/VerticalAlignment is set to stretch, of course the path will scale.

For other values of Horizontal-/VerticalAlignment however, the button size gets determined by the amount of space required by its content, which in my case resulted in a button with the path's original dimensions.

Mike Fuchs
  • 12,081
  • 6
  • 58
  • 71
0

If you want this with a constant stroke width that isn't scaled, you can use a custom Shape. Shapes in WPF effectively encapsulate scaling a geometry and applying a stroke afterwards, which means you can have a scaled path that also always has the same stroke width.

Creating a shape is quite easy:

public class MyShape : Shape
{
  public override Geometry DefiningGeometry
  {
    get
    {
      // Create your geometry here
    }
  }
}
Joey
  • 344,408
  • 85
  • 689
  • 683