wpf ClipToBounds right and bottom - wpf

How to clip path stroke? With ClipToBounds="True" there are unwanted pieces at rigth and bottom side.
<Grid Background="Yellow" ClipToBounds="True">
<Viewbox Stretch="Fill">
<Path Data="M30,0 L0,10 L0,40 L30,50 L30,0" Stroke="Red" StrokeThickness="5" />
</Viewbox>
</Grid>
EDIT
I figured out that I just need not to scale border thickness, so solution will be:
<Grid x:Name="grid" Grid.Row="2" Background="Yellow" >
<Grid.Resources>
<ScaleTransform x:Key="transform"
ScaleX="{Binding ActualWidth, ElementName=grid}"
ScaleY="{Binding ActualHeight, ElementName=grid}" />
</Grid.Resources>
<Path Stroke="Red" StrokeThickness="15" Stretch="Fill">
<Path.Data>
<PathGeometry Transform="{StaticResource transform}">
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure IsClosed="True" StartPoint="0,0.7">
<PathFigure.Segments>
<PathSegmentCollection>
<LineSegment Point="1,1" />
<LineSegment Point="1,0" />
<LineSegment Point="0,0.3" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
</Grid>

If it's ok not to scale the stroke thickness, you might drop the Viewbox and set Stretch="Fill" directly at the Path:
<Grid Background="Yellow" ClipToBounds="True" Margin="20">
<Path Stretch="Fill" Data="M30,0 L0,10 L0,40 L30,50 L30,0 Z"
Stroke="Red" StrokeThickness="20" />
</Grid>
Otherwise you might use the Path in a VisualBrush in e.g. a Rectangle (which needs to have some size set explicitly):
<Grid Background="Yellow" ClipToBounds="True" Margin="20">
<Viewbox Stretch="Fill">
<Rectangle Width="1" Height="1">
<Rectangle.Fill>
<VisualBrush>
<VisualBrush.Visual>
<Path Data="M30,0 L0,10 L0,40 L30,50 L30,0 Z"
Stroke="R*emphasized text*ed" StrokeThickness="5" />
</VisualBrush.Visual>
</VisualBrush>
</Rectangle.Fill>
</Rectangle>
</Viewbox>
</Grid>
Please also note that the path geometry is closed by a trailing Z.

Related

Why does this polyline not fit inside the ViewBox in WPF?

What I am trying to achieve is to fit the Polyline inside a Viewbox. I tried the Stretch options, however it does not seem to work with negative values. Can someone guide how to fit the content inside the ViewBox?
Following is my sample code:
<Viewbox Stretch="Uniform">
<Grid>
<Polyline Margin="10" Fill="Tan" HorizontalAlignment="Center"
VerticalAlignment="Center" Points="0,0 14,0 14,-38"
StrokeThickness="1" Stroke="Black"
RenderTransformOrigin="0.5,0.5">
<Polyline.RenderTransform>
<TransformGroup>
<RotateTransform Angle="180"/>
<ScaleTransform>
<ScaleTransform.ScaleX>-1</ScaleTransform.ScaleX>
</ScaleTransform>
</TransformGroup>
</Polyline.RenderTransform>
</Polyline>
</Grid>
</Viewbox>
The bounds go beyond the Viewbox, hence unable to get it to "fit" the view.
You shouldn't set the RenderTransform of an element in a Viewbox.
Instead of a Polyline you may use a Path with a polyline geometry, where you can set the Transform property of the Geometry object in the Path's Data:
<Viewbox Stretch="Uniform">
<Path Margin="10" Fill="Tan" StrokeThickness="1" Stroke="Black"
HorizontalAlignment="Center" VerticalAlignment="Center">
<Path.Data>
<PathGeometry Figures="M0,0 L14,0 14,-38">
<PathGeometry.Transform>
<TransformGroup>
<RotateTransform Angle="180"/>
<ScaleTransform>
<ScaleTransform.ScaleX>-1</ScaleTransform.ScaleX>
</ScaleTransform>
</TransformGroup>
</PathGeometry.Transform>
</PathGeometry>
</Path.Data>
</Path>
</Viewbox>
Edit: An alternative might be to set the LayoutTransform instead of RenderTransform. You would also have to set the Polyline's Stretch property:
<Viewbox>
<Polyline Margin="10" Fill="Tan" StrokeThickness="1" Stroke="Black"
Points="0,0 14,0 14,-38" Stretch="Uniform">
<Polyline.LayoutTransform>
<TransformGroup>
<RotateTransform Angle="180"/>
<ScaleTransform>
<ScaleTransform.ScaleX>-1</ScaleTransform.ScaleX>
</ScaleTransform>
</TransformGroup>
</Polyline.LayoutTransform>
</Polyline>
</Viewbox>

How to create round line caps in circular progress bar

So i have this Circular Progress-Bar:
<Grid>
<Grid>
<Border>
<Path x:Name="pathRoot"
Stroke="{Binding SegmentColor, ElementName=userControl}"
StrokeThickness="{Binding StrokeThickness, ElementName=userControl}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Height="100"
Width="100">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure x:Name="pathFigure">
<PathFigure.Segments>
<PathSegmentCollection>
<ArcSegment x:Name="arcSegment" SweepDirection="Clockwise"/>
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
</Border>
</Grid>
</Grid>
And i want my Circle border will be rounded, for example:
Any idea how to do that ?
I try to put my main Grid inside border with some corner value but this did not wirk..

Converting SVG to XAML

I know this question has already been answered, as I have followed the instructions of these answers. I have a .SVG image of an icon, which I am trying to convert into useable XAML code, I am using my images like this;
<ControlTemplate x:Uid="ControlTemplate_9" x:Key="IconTemplate">
<Viewbox xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Stretch="Uniform">
<Canvas Name="svg2" Width="24" Height="16" ToolTip="IconToolTip.">
<Canvas.RenderTransform>
<TranslateTransform X="0" Y="0"/>
</Canvas.RenderTransform>
<Canvas.Resources/>
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path16" Fill="#FFFCF0F0">
<Path.Data>
<PathGeometry Figures=" M 22.30" FillRule="NonZero"/>
</Path.Data>
</Path>
</Canvas>
</Viewbox>
</ControlTemplate>
When I picked up this system most of these were already provided, but my issue is adding more to it. When using programs such as Inkscape or printing to PDF and opening the .fpage file I am getting .XAML along the lines of -
<?xml version="1.0" encoding="UTF-8"?>
<!--This file is NOT compatible with Silverlight-->
<Viewbox xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Stretch="Uniform">
<Canvas Name="svg2" Width="24" Height="16">
<Canvas.RenderTransform>
<TranslateTransform X="0" Y="0"/>
</Canvas.RenderTransform>
<Canvas.Resources/>
<!--Unknown tag: metadata-->
<!--Unknown tag: sodipodi:namedview-->
<Rectangle xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="24" Height="16" RadiusX="4" RadiusY="4" Name="Rounded_Rectangle_1" Fill="#000000"/>
<Rectangle xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Canvas.Left="11" Canvas.Top="3" Width="2" Height="6" Name="rect9" Fill="#000000"/>
<Image xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="image11" Canvas.Left="11" Canvas.Top="11" Source="data:img/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAQAAAABazTCJAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfgCRoPHAwMuTLjAAAADElEQVQI12M4wHAAAAMEAYHFO6KpAAAAAElFTkSuQmCC" Width="2" Height="2"/>
</Canvas>
</Viewbox>
The latter will not compile and causes the program to crash. So my extension to the previous questions would be, how do I use the latter XAML in my codebase without directly having an image in the project folder or how do I convert this into useable path data.
What I have done and which is actually working perfectly is to remove all the part with xml:
<Viewbox Stretch="Uniform">
<Canvas Name="svg2" Width="24" Height="16">
<Canvas.RenderTransform>
<TranslateTransform X="0" Y="0"/>
</Canvas.RenderTransform>
<Canvas.Resources/>
<Rectangle Width="24" Height="16" RadiusX="4" RadiusY="4" Name="Rounded_Rectangle_1" Fill="#000000"/>
<Rectangle Canvas.Left="11" Canvas.Top="3" Width="2" Height="6" Name="rect9" Fill="#000000"/>
<Image Name="image11" Canvas.Left="11" Canvas.Top="11" Source="data:img/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAQAAAABazTCJAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfgCRoPHAwMuTLjAAAADElEQVQI12M4wHAAAAMEAYHFO6KpAAAAAElFTkSuQmCC" Width="2" Height="2"/>
</Canvas>
</Viewbox>
And I have added them to a ResourceDictionary, so they can be used in the whole project.
<Viewbox x:Key="MyIcon" x:Shared="False" Stretch="Uniform">
<Canvas Name="svg2" Width="24" Height="16">
<Canvas.RenderTransform>
<TranslateTransform X="0" Y="0"/>
</Canvas.RenderTransform>
<Canvas.Resources/>
<Rectangle Width="24" Height="16" RadiusX="4" RadiusY="4" Name="Rounded_Rectangle_1" Fill="#000000"/>
<Rectangle Canvas.Left="11" Canvas.Top="3" Width="2" Height="6" Name="rect9" Fill="#000000"/>
<Image Name="image11" Canvas.Left="11" Canvas.Top="11" Source="data:img/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAQAAAABazTCJAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfgCRoPHAwMuTLjAAAADElEQVQI12M4wHAAAAMEAYHFO6KpAAAAAElFTkSuQmCC" Width="2" Height="2"/>
</Canvas>
</Viewbox>

Bind the height of a Polygon to the StackPanel height

I can't figure how to bind the height of a polygon to the height of my stack panel.
If I wanted to add a rectangle, all I had to do is something like that:
<Rectangle Width="75" >
<Rectangle.Fill>
<SolidColorBrush Color="Red" />
</Rectangle.Fill>
</Rectangle>
This one won't brake the height of the panel. but with the polygon it seems like I can't leave some of the points as blank so that will scale with the parent panel.
Thanks
Wrap your polygon with a <Viewbox>.
The Viewbox automatically scales its content to its size. Exactly how it does so can be tweaked with the Stretch and StretchDirection properties.
this solution works too
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Border BorderBrush="Black" BorderThickness="1,1,0,1">
<StackPanel Orientation="Horizontal">
<TextBlock Text="TextBlock1" Margin="2" />
<TextBlock Text="TextBlock2" Margin="2" />
<TextBlock Text="TextBlock3" Margin="2" />
<TextBlock Text="TextBlock4" Margin="2" />
<TextBlock Text="TextBlock5" Margin="2" />
</StackPanel>
</Border>
<Path Fill="Yellow" Stroke="Black" StrokeThickness="1"
Width="50" Stretch="Fill">
<Path.Data>
<PathGeometry>
<PathFigure IsClosed="True" StartPoint="1,0.5">
<LineSegment Point="0,0" IsSmoothJoin="True" />
<LineSegment Point="0,1" IsSmoothJoin="True" />
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
</StackPanel>
</Grid>

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?
I've done this by scaling a Path's Data, not the visual component.
Place a Path in a Canvas.
Set path.Data to a Geometry representing your data as percentages of the logical range.
Set path.Data.Transform to a ScaleTransform with ScaleX and ScaleY bound to the actual width and height.
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>
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:

Resources