WPF Show part of drawing path - wpf

I have a drawing with <Path> element. It contains dificult Data attribute so how I can show part of this path.

There are certainly several ways to do this. A very easy one would be to put the Path in a Canvas, set its position inside the Canvas and clip it by the Canvas' bounds:
<Canvas Width="80" Height="60" ClipToBounds="True">
<Path Canvas.Left="-10" Canvas.Top="-10" Data="M0,0 L100,0 100,100 Z"
Stroke="Black" StrokeThickness="2" Fill="AliceBlue"/>
</Canvas>

make use of Blend tool for this where if you copy the data attribute for the path, you could see how it is generated.
It would make your job easier to modify the path as well see the data generation at the same time.

Related

Can I use a ViewBox as a Source for an Image in WPF?

I have an icon that's defined in XAML and the root element is Viewbox. I would like to set that as a Source of an Image element.
I tried to set it directly as a source for an Image like...
<Button Margin='5'>
<Image Source='{StaticResource IconKey}'></Image>
</Button>
But I get an exception. Is there a way to do that?
This is kind of a big subject and tricky for beginners because there's so much "stuff" you need to get your head round.
I'll try and cover a few things around the subject. Hopefully that might reduce your confusion a little.
A Path uses data which looks a bit weird what with all that strange co-ordinate stuff. This can go directly in a path, or in a Geometry ( or a stream geometry ). If you use a geometry then that is re-usable for a red-whatever blue-whatever etc. It is also not a visual so you don't get caught out by visuals only being able to have the one parent - ie one use in any ui.
The way I'd usually go about this sort of thing is to obtain a single geometry.
Often out of syncfusion metro studio ( which is a free library ) but sometimes I use inkscape ( free ) to trace a bitmap or I get a path out a svg.
You can however combine two geometries.
In a resource dictionary merged by app.xaml you could have a geometry:
<CombinedGeometry x:Key="TwoGeometriesInOne">
<CombinedGeometry.Geometry1>
<Geometry>
M3,1.6675c0,-0.1795..... and the rest of your first geometry data
</Geometry>
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<Geometry>
M15.9289,7.776L5.285,....
</Geometry>
</CombinedGeometry.Geometry2>
</CombinedGeometry>
Huge long strings mess up the site, but those two geometries should just have the M... through to the z of that data you're using for each path.
Use that in a button ( or any other content control )
<Button Height="40" Width="40">
<Path Fill="#3E79B4" Data="{StaticResource TwoGeometriesInOne}"
Height="16"
Width="16"
Stretch="Fill"/>
</Button>
Note that a path can just be used on it's own rather than in a canvas and sized, it can also be stretched to fit it's size or whatever the parent allows.
Consider also:
<Button Height="40" Width="40">
<Path Fill="#3E79B4" Data="{StaticResource TwoGeometriesInOne}"
Stretch="UniformToFill"
Margin="5"
/>
</Button>
With a path you have fill and stroke. Stroke is the outline. If you want different coloured shapes in one "icon" then a drawingimage with multiple geometrydrawing would be more suitable because each geometryimage can have it's own brush.
I found an alternative. Instead of Using an Image inside the button I used Button's Content attribute.
<Button Content='{StaticResource IconKey}' />

WPF OpacityMask weird behavior

I think I might have found a bug in WPF, or maybe I just don't fully understand how OpacityMasks work. As you can see on the first image, I have a diamond shaped path and a red circle. My goal is to make everything outside the diamond invisible. It works when the circle is inside the diamond shape, but whenever I move it to one of the corners, or outside the path, the OpacityMask seems to get stretched or distorted as you can see on the second image. My question is how can I make the OpacityMask work regardless of where the circle (or any other child element) is.
First image
Second Image
And this is my XAML code
<Grid Name="rootGrid">
<Grid>
<Grid.OpacityMask>
<VisualBrush Visual="{Binding ElementName=path}"/>
</Grid.OpacityMask>
<Path Name="path"
Stretch="Fill"
Fill="Cyan"
StrokeThickness="1"
Stroke="GreenYellow"
Data="M 0,-1 1,0 0,1 -1,0 0,-1"/>
<Ellipse Fill="Red"
Margin="20,-17,22,61"/>
</Grid>
</Grid>
Sorry for posting the images with links, but I don't have enough reputation to directly embed images.
Any help is appreciated!
Clemens solved my issue
Set ViewportUnits="Absolute" on the VisualBrush, and then set its Viewport property to an appropriate rectangle, e.g. Viewport="0,0,100,100"

XAML Border vs Rectangle

I want to get a window like this
How should i get this and i am confused between Border and Rectangle in XAML.
Border is a container control aos its use is pretty simple to get, what is the use of ractangle as it can't contain any control in it.
Kindly help
Neither Border nor Rectangle will achieve this, you probably need a Path or something similar.
I would like to answer your last question
What is the use of ractangle as it can't contain any control in it.
Yes it can't contain any controls, but you can always draw it in the background
<Grid>
<Rectangle/>
<TextBlock/>
</Grid>
The user will propably don't see any difference. Why having two different Controls for that? Not sure, but my guess is that a Border is a shortcut to have a rectangle around a control, there might be more behind it, but thats how i see it. Also a Rectangle is a Shape, and it makes sense to have a Rectangle besides an Ellipse, Line etc.
You can draw a plygon as follow:
<Polygon
Points="100 50, 100 150,250 150, 250 75, 225 50"
Stroke="Black"
StrokeThickness="2">
<Polygon.Fill>
<SolidColorBrush Color="White"/>
</Polygon.Fill>
</Polygon>
Here you can find some other interesting example
This path is like your shape, if you use Expression Blend you can draw it into the editor.
<Path Data="M20.5,0.5 L153.81876,0.5 194.5,41.181242 194.5,103.5 C194.5,114.54569 185.5457,123.5 174.5,123.5 L20.5,123.5 C9.4543047,123.5 0.5,114.54569 0.5,103.5 L0.5,20.500004 C0.5,9.4543067 9.4543047,0.50000197 20.5,0.5 z" Fill="#FFF4F4F5" Stretch="Fill" Stroke="Black" HorizontalAlignment="Left" Height="124" VerticalAlignment="Top" Width="195"/>

OpacityMask not working with WPF WindowsFormsHost?

I'm trying to put a rounded border on a control which is hosted through a WindowsFormHost object. It seems like no matter what I set for OpacityMask, it has no effect on the rendering. Is there something I've missed?
Here is the XAML code I am using. The child control is added at run-time. I've tried various combinations of masks, none of which worked for me. Any help would be appreciated. Thanks!
<WindowsFormsHost Background="#FF2BBA62" Height="414" Width="516" Margin="176.5,223,309.5,92" Name="vcxHost1" UseLayoutRounding="False" ClipToBounds="True" >
<WindowsFormsHost.OpacityMask>
<VisualBrush>
<VisualBrush.Visual>
<Rectangle Height="10" Width="100" Name="border1" />
</VisualBrush.Visual>
</VisualBrush>
</WindowsFormsHost.OpacityMask>
</WindowsFormsHost>
I suspect it doesn't work for the same reason that the z-indexing doesn't work. From the linked doc: "A hosted Windows Forms control is drawn in a separate HWND, so it is always drawn on top of WPF elements."
See the paragraph on Layout Limitations ...
http://msdn.microsoft.com/en-us/library/ms744952.aspx
This may also be helpful ... http://msdn.microsoft.com/en-us/library/ms742522.aspx

What is the Data value of plus sign in Path

How to draw plus and minus signs in using data property in Path object.
This is my triangle path object. I need to change it to plus symbol.
<Path x:Name="trianglePath" Data="M 0 8 H 12 V 15 Z"/>
Here, I've created a plus and minus sign which is 10 x 10 pixels using XAML path markup syntax:
<Path Margin="10" Stroke="White" Data="M0,5 H10 M5,5 V10Z" StrokeThickness="2" Height="10" Width="10" />
<Path Margin="10" Stroke="White" Data="M0,5 H10" StrokeThickness="2" Height="10" Width="10" />
When experimenting with designing your path drawing, it's helpful to set the path element's height & width first. To better understand XAML path markup syntax, see MSDN.
You might find it easier if you draw them out on a piece of graph paper and then label the vertices with the values needed to reach it from the previous one.
Then copy this into your code.

Resources