How to translate objects with different parent together wpf Canvas and Grid - wpf

I'm trying to do a Rotate/Translate/Scale of objects using a canvas for the actual figure and I use a Grid for "thumbs" container (Thumbs are some small ellipses)
I have some trouble understanding the logic behind this example.
<Window x:Class="RotateMe.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:RotateMe"
mc:Ignorable="d"
Title="MainWindow" Height="300" Width="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button x:Name="AddRectangle" Width="50" Grid.Row="0" HorizontalAlignment="Left" Click="AddRectangle_Click"/>
<Canvas x:Name="DrawingCanvas" Grid.Row="1" Background="Gray">
<Ellipse x:Name="Thumb3" Fill="Azure" Height="10" Width="10" >
<Ellipse.RenderTransform>
<TranslateTransform X="-50" Y="-50"/>
</Ellipse.RenderTransform>
</Ellipse>
<Ellipse x:Name="Thumb4" Fill="Beige" Height="10" Width="10" >
<Ellipse.RenderTransform>
<TranslateTransform X="50" Y="50"/>
</Ellipse.RenderTransform>
</Ellipse>
</Canvas>
<Grid x:Name="ThumbsParent" Grid.Row="1" RenderTransformOrigin="1,1">
<Ellipse x:Name="Thumb" Fill="Red" Height="10" Width="10" RenderTransformOrigin="1,1">
<Ellipse.RenderTransform>
<TranslateTransform X="-50" Y="-50"/>
</Ellipse.RenderTransform>
</Ellipse>
<Ellipse x:Name="Thumb2" Height="10" Width="10" Fill="Green">
<Ellipse.RenderTransform>
<TranslateTransform X="50" Y="50"/>
</Ellipse.RenderTransform>
</Ellipse>
</Grid>
</Grid>
</Window>
So here I have
A Grid over an Canvas (same size)
Each of them contain a 10/10 ellipse that one is render transform -50/-50 and one is 50/50.
I would have expected the same behavior (overlap of the ellipses on both -50/-50 and 50/50)
Instead it looks like this.
So from what I understand from this.
Grid renders from CenterX/CenterY
Canvas renders from 0/0.
Is there a particular reason this is happening?
Why I am asking this, because I wanted to use a TranslateTransform for all my object and if one moves, all should move, but because one translate from 0/0 and one from CenterX/CenterY the same translate won't work on these elements.

Related

Rotate border from bottom

I want to rotate a border But the rotation is done from the middle of the border, I want the rotation to be done from the end of the border just like a clock that rotates around a circle
this is my codes:
<ed:Arc
StartAngle="0" EndAngle="360" Stretch="None"
Height="300" Width="300" StrokeThickness="20"
StrokeDashArray=".25" Stroke="Turquoise"/>
<Border HorizontalAlignment="Center" CornerRadius="100,100,0,0" RenderTransformOrigin="0,0.5" Height="140" Width="2" BorderBrush="Red" BorderThickness="2">
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="40"/>
<TranslateTransform/>
</TransformGroup>
</Border.RenderTransform>
</Border>
Upper left corner:
<Border ....
RenderTransformOrigin="0,0">
<Border.RenderTransform>
<RotateTransform Angle="40"/>
</TextBox.RenderTransform>
</TextBox>
A couple more examples:
Bottom right corner - RenderTransformOrigin="1,1"
Middle of the bottom side - RenderTransformOrigin="0.5,1"
When you are creating drawings, it is often useful to use a Canvas and position child elements by means of the Canvas.Left and Canvas.Top properties.
Thus you would not have to deal with any offsets when you want to transform the elements. The element transforms could be calculated in their "local" coordinate system, like the one of the "clock hand" Line element in the example below, which goes from (0,0) to (0,-140) in the 12 o'clock position.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Canvas Width="300" Height="300">
<Ellipse Width="300" Height="300" Stroke="Turquoise"
StrokeThickness="20" StrokeDashArray=".25"/>
<Line Canvas.Left="150" Canvas.Top="150"
Y2="-140" Stroke="Red" StrokeThickness="2" >
<Line.RenderTransform>
<RotateTransform Angle="{Binding Value,
ElementName=angleSlider}"/>
</Line.RenderTransform>
</Line>
</Canvas>
<Slider x:Name="angleSlider" Grid.Row="1" Width="200" Maximum="360"/>
</Grid>

WPF - Draw curved line from center screen to margin that dynamically adapts as the screen changes

I want to draw a curved line from the center of the screen to the top left margin. As the window resizes the line should change it's coordinates.
Is it possible to do this respecting MVVM ?
Example:
Note that a Viewbox scales the rendered output of its content (including e.g. the StrokeThickness of a Path), but not the geometry of a drawing.
The following approach works without scaling the StrokeThickness, because the Ellipse control scales its geometry to fit its bounds:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border ClipToBounds="True">
<Ellipse Stroke="Black" StrokeThickness="1" RenderTransformOrigin="0,1">
<Ellipse.RenderTransform>
<ScaleTransform ScaleX="2" ScaleY="2"/>
</Ellipse.RenderTransform>
</Ellipse>
</Border>
</Grid>
Create a grid in your window with 2 columns both with a width of 1*
To your grid in the first column add a viewbox with StretchDirection = Both and Stretch = Fill
Within the viewbox add your curve.
As the window resizes the columns will get smaller and the viewbox will stetch the contents down.
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Viewbox StretchDirection="Both" Stretch="Fill">
<Canvas Width="100" Height="200">
<Path Stroke="Black" StrokeThickness="3">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigure StartPoint="0,0" IsClosed="False">
<ArcSegment Point="100,100" Size="100 100"/>
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
</Canvas>
</Viewbox>
</Grid>

Button inside a custom skewed window doesn't allways get mouseEnter event

Here is my code:
<Window x:Class="WPFStackOverFlow.SkewWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
AllowsTransparency="True" WindowStyle="None" Background="Transparent"
Title="MainWindow" Height="600" Width="687">
<Border BorderBrush="Green" BorderThickness="2" Background="White" Width="360" Height="360">
<Border.RenderTransform>
<SkewTransform AngleX="-23" AngleY="10"></SkewTransform>
</Border.RenderTransform>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="23" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button Grid.Row="0" Content="X" Width="23" Name="button1" HorizontalAlignment="Right" Click="button1_Click" Height="23" VerticalAlignment="Bottom"/>
<Grid Grid.Row="1">
<Button Height="100" Width="200"></Button>
<TextBlock Text="Some very very long Text" HorizontalAlignment="Center"/>
</Grid>
</Grid>
</Border>
When I move the mouse cursor over the button sometimes it get focus and sometimes it doesn't. How can I make the button inside this custom window to be like a button in a regular window?
I don't think you can apply transformations to windows.
You can apply them to the controls inside windows.
If you need to simulate transformations to windows you can try something similar to what is described in the answer to this question.

Image blocks out Canvas

<Image Width="640" Height="480" Name="ImageControl" Grid.Column="0" Grid.Row="1" />
<Canvas Width="620" Height="480" Name="myCanvas" Grid.Column="0" Grid.Row="1" >
<Ellipse Width="10" Height="10" Fill="Red" Canvas.Left="610" Canvas.Top="10" Name="Circle1" Canvas.ZIndex="99" />
<Ellipse Width="10" Height="10" Fill="Red" Canvas.Left="610" Canvas.Top="30" Name="Circle2" />
<Ellipse Width="10" Height="10" Fill="Red" Canvas.Left="610" Canvas.Top="50" Name="Circle3" />
<Ellipse Width="10" Height="10" Fill="Red" Canvas.Left="610" Canvas.Top="70" Name="Circle4" />
<Ellipse Width="10" Height="10" Fill="Red" Canvas.Left="610" Canvas.Top="90" Name="Circle5" />
<Ellipse Width="10" Height="10" Fill="Red" Canvas.Left="610" Canvas.Top="110" Name="Circle6" />
<Ellipse Width="10" Height="10" Fill="Red" Canvas.Left="610" Canvas.Top="130" Name="Circle7" />
<Ellipse Width="10" Height="10" Fill="Red" Canvas.Left="610" Canvas.Top="150" Name="Circle8" />
</Canvas>
I have an Image and a Canvas in the same cell in a Grid. The idea is to place the 8 red ellipses over the image. The Image currently has no source as the Kinect is used to supply the image. When it first loads the red ellipses can be seen for a split second until the image loads and then they aren't seen again.
I have tried changed the order of the elements, the ZIndex of the Canvas, the ZIndex of the Grid all with no avail.
this.ImageControl.Source = BitmapSource.Create(
imageFrame.Width,
imageFrame.Height,
96,
96,
PixelFormats.Bgr32,
null,
this.pixelData,
stride);
This is how the Kinect stream image is assigned to the Image source.
Have you tried to use a different imagesource?
It works for me.
Try to use one of the Example Pictures from Windows.
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="537" Width="721">
<Grid>
<Image Width="640" Height="480" Name="ImageControl" Grid.Column="0" Grid.Row="1" Source="Desert.jpg" />
<Canvas Width="620" Height="480" Name="myCanvas" Grid.Column="0" Grid.Row="1" >
<Ellipse Width="10" Height="10" Fill="Red" Canvas.Left="610" Canvas.Top="10" Name="Circle1" Canvas.ZIndex="99" />
<Ellipse Width="10" Height="10" Fill="Red" Canvas.Left="610" Canvas.Top="30" Name="Circle2" />
<Ellipse Width="10" Height="10" Fill="Red" Canvas.Left="610" Canvas.Top="50" Name="Circle3" />
<Ellipse Width="10" Height="10" Fill="Red" Canvas.Left="610" Canvas.Top="70" Name="Circle4" />
<Ellipse Width="10" Height="10" Fill="Red" Canvas.Left="610" Canvas.Top="90" Name="Circle5" />
<Ellipse Width="10" Height="10" Fill="Red" Canvas.Left="610" Canvas.Top="110" Name="Circle6" />
<Ellipse Width="10" Height="10" Fill="Red" Canvas.Left="610" Canvas.Top="130" Name="Circle7" />
<Ellipse Width="10" Height="10" Fill="Red" Canvas.Left="610" Canvas.Top="150" Name="Circle8" />
</Canvas>
</Grid>
</Window>
Turns out I head this in my code
myCanvas.Children.Clear();
This was clearing the line skeleton drawn on the canvas once it was no longer needed and this was removing the ellipses as well.

Getting a path to overlap a rectangle or other control

I have the following XAML :
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DockPanel Margin="5">
<Path Stroke="Black" StrokeThickness="1" Fill="White" DockPanel.Dock="Left" VerticalAlignment="Center">
<Path.Data>
<GeometryGroup>
<LineGeometry StartPoint="10,0" EndPoint="0,10" />
<LineGeometry StartPoint="0,10" EndPoint="10,20" />
</GeometryGroup>
</Path.Data>
</Path>
<Rectangle Stroke="Black" RadiusX="10" RadiusY="10"/>
</DockPanel>
</Page>
It creates like a speech bubble. However I would like the part where the two join to be white or not to have any stroke.
Not very clever, but perhaps sufficient:
<DockPanel Margin="5">
<Path Stroke="Black" StrokeThickness="1"
Fill="White" DockPanel.Dock="Left" VerticalAlignment="Center"
Panel.ZIndex="1" Margin="0,0,-1,0" Data="M10,0 L0,10 10,20"/>
<Rectangle Stroke="Black" RadiusX="10" RadiusY="10"/>
</DockPanel>
A better solution might be to create a CombinedGeometry from the Path and the Rectangle.
If you have access to Blend you can use the Callout control, which does exactly what you want.
It resides in this assembly:
C:\Program Files (x86)\Microsoft SDKs\Expression\Blend\.NETFramework\v4.0\Libraries\Microsoft.Expression.Drawing.dll
and is used like that:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing" x:Class="WpfApplication1.MainWindow"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ed:Callout AnchorPoint="-0.061,0.716" CalloutStyle="RoundedRectangle" Content="Callout" Fill="#FFF4F4F5" FontSize="14.667" HorizontalAlignment="Left" Height="109" Margin="61,78,0,0" Stroke="Black" VerticalAlignment="Top" Width="375"/>
</Grid>
</Window>
Edit: if you have Blend (for VS 2012) you can easily draw a path yourself that looks like a callout.
Example:
<Path Data="M110.029,0.5 L305.895,0.5 C314.17927,0.50000358 320.895,7.2157323 320.895,15.500005 L320.895,144.202 C320.895,152.48627 314.17927,159.202 305.895,159.202 L110.029,159.202 C101.74473,159.202 95.028999,152.48627 95.029,144.202 L95.029,119.139 0.5,94.029644 94.530329,44.776012 95.029,69.723011 95.029,15.500005 C95.028999,7.2157323 101.74473,0.50000358 110.029,0.5 z" Fill="#FFF4F4F5" HorizontalAlignment="Left" Height="159.702" Margin="122.366,45.642,0,0" Stretch="Fill" Stroke="Black" VerticalAlignment="Top" Width="321.395"/>

Resources