I've created a Windows Store Application in visual studio 2013, and I really don't know how to rotate a button on PointerEntered in c#. Using hover, I just want to rotate it to 360 angle. I would appreciate it if somebody will help me.
Here is an example from MSDN:
The XAML:
<Canvas Height="200" Width="200">
<!-- Rotates the Polyline 45 degrees about the point (0,0). -->
<Polyline Points="25,25 0,50 25,75 50,50 25,25 25,0"
Stroke="Blue" StrokeThickness="10"
Canvas.Left="75" Canvas.Top="50">
<Polyline.RenderTransform>
<RotateTransform CenterX="0" CenterY="0" Angle="45" />
</Polyline.RenderTransform>
</Polyline>
</Canvas>
The c# Code:
(Use this as and where required...)
// Create a Polyline.
Polyline polyline1 = new Polyline();
polyline1.Points.Add(new Point(25, 25));
polyline1.Points.Add(new Point(0, 50));
polyline1.Points.Add(new Point(25, 75));
polyline1.Points.Add(new Point(50, 50));
polyline1.Points.Add(new Point(25, 25));
polyline1.Points.Add(new Point(25, 0));
polyline1.Stroke = Brushes.Blue;
polyline1.StrokeThickness = 10;
// Create a RotateTransform to rotate
// the Polyline 45 degrees about its
// top-left corner.
RotateTransform rotateTransform1 =
new RotateTransform(45);
polyline1.RenderTransform = rotateTransform1;
// Create a Canvas to contain the Polyline.
Canvas canvas1 = new Canvas();
canvas1.Width = 200;
canvas1.Height = 200;
Canvas.SetLeft(polyline1, 75);
Canvas.SetTop(polyline1, 50);
canvas1.Children.Add(polyline1);
Related
Does anyone know of an easy way to animate a movement from an Image's current location to a new location (X,Y) using WPF animation with no XAML, 100% programmatically? And with no reference to "this" (with RegisterName etc).
I am trying to make an extension class for Image to do animation stuff on it. It is easy enough to change the width and height properties through animation, but after searching for location animation of an object it suddenly becomes more advanced.
As it is an extension class I will only have a reference to the actual Image object and the X and Y I want to move it to.
public static void MoveTo(this Image targetControl, double X, double Y, double Width, double Height){
//code here
...
}
Update:
Thanks. Almost working. It seems The GetTop and GetLeft returns 'NaN' not explicitly set. Found the workaround in this post: Canvas.GetTop() returning NaN
public static void MoveTo(this Image target, double newX, double newY) {
Vector offset = VisualTreeHelper.GetOffset(target);
var top = offset.Y;
var left = offset.X;
TranslateTransform trans = new TranslateTransform();
target.RenderTransform = trans;
DoubleAnimation anim1 = new DoubleAnimation(0, newY - top, TimeSpan.FromSeconds(10));
DoubleAnimation anim2 = new DoubleAnimation(0, newX - left, TimeSpan.FromSeconds(10));
trans.BeginAnimation(TranslateTransform.YProperty, anim1);
trans.BeginAnimation(TranslateTransform.XProperty, anim2);
}
I had to swap two of the values (FROM) with 0. I assume that must be because in this context the upper left corner of the picture is the origin? But now it works.
Try this:
public static void MoveTo(this Image target, double newX, double newY)
{
var top = Canvas.GetTop(target);
var left = Canvas.GetLeft(target);
TranslateTransform trans = new TranslateTransform();
target.RenderTransform = trans;
DoubleAnimation anim1 = new DoubleAnimation(top, newY - top, TimeSpan.FromSeconds(10));
DoubleAnimation anim2 = new DoubleAnimation(left, newX - left, TimeSpan.FromSeconds(10));
trans.BeginAnimation(TranslateTransform.XProperty,anim1);
trans.BeginAnimation(TranslateTransform.YProperty,anim2);
}
Here it is... It changes the size and moves a MediaElement under the Canvas. Just input your parameters:
Storyboard story = new Storyboard();
DoubleAnimation dbWidth = new DoubleAnimation();
dbWidth.From = mediaElement1.Width;
dbWidth.To = 600;
dbWidth.Duration = new Duration(TimeSpan.FromSeconds(.25));
DoubleAnimation dbHeight = new DoubleAnimation();
dbHeight.From = mediaElement1.Height;
dbHeight.To = 400;
dbHeight.Duration = dbWidth.Duration;
story.Children.Add(dbWidth);
Storyboard.SetTargetName(dbWidth, mediaElement1.Name);
Storyboard.SetTargetProperty(dbWidth, new PropertyPath(MediaElement.WidthProperty));
story.Children.Add(dbHeight);
Storyboard.SetTargetName(dbHeight, mediaElement1.Name);
Storyboard.SetTargetProperty(dbHeight, new PropertyPath(MediaElement.HeightProperty));
DoubleAnimation dbCanvasX = new DoubleAnimation();
dbCanvasX.From = 0;
dbCanvasX.To = 5;
dbCanvasX.Duration = new Duration(TimeSpan.FromSeconds(.25));
DoubleAnimation dbCanvasY = new DoubleAnimation();
dbCanvasY.From = 0;
dbCanvasY.To = 5;
dbCanvasY.Duration = dbCanvasX.Duration;
story.Children.Add(dbCanvasX);
Storyboard.SetTargetName(dbCanvasX, mediaElement1.Name);
Storyboard.SetTargetProperty(dbCanvasX, new PropertyPath(Canvas.LeftProperty));
story.Children.Add(dbCanvasY);
Storyboard.SetTargetName(dbCanvasY, mediaElement1.Name);
Storyboard.SetTargetProperty(dbCanvasY, new PropertyPath(Canvas.TopProperty));
story.Begin(this);
<Viewbox Stretch="Uniform" StretchDirection="Both" SnapsToDevicePixels="True">
<Grid Width="640" Height="480" Name="MainLayout" SnapsToDevicePixels="True" Background="Black">
<Canvas Width="640" Height="480" Name="MainCanvas" SnapsToDevicePixels="True">
<MediaElement Height="171" HorizontalAlignment="Left" Name="mediaElement1" VerticalAlignment="Top" Width="337" LoadedBehavior="Manual" Margin="166,140,0,0" Canvas.Left="-162" Canvas.Top="-140" />
<Button Canvas.Left="294" Canvas.Top="196" Content="Button" Height="23" Name="button1" Width="75" Click="button1_Click" />
</Canvas>
</Grid>
</Viewbox>
UPDATE:
Instead of MediaElement use this line:
<Rectangle Height="171" HorizontalAlignment="Left" Name="mediaElement1" VerticalAlignment="Top" Width="337" Margin="166,140,0,0" Canvas.Left="-162" Canvas.Top="-140" Fill="{DynamicResource {x:Static SystemColors.MenuBarBrushKey}}" />
And don't forget to put the C# code to:
private void button1_Click(object sender, RoutedEventArgs e) {}
You can use MediaElement as well but you have to define a VideoClip to see something ;)
Please find a solution that uses the Left and Top properties of Canvas for the extension method. See the following code:
public static void MoveTo(this Image target, Point newP)
{
Point oldP = new Point();
oldP.X = Canvas.GetLeft(target);
oldP.Y = Canvas.GetTop(target);
DoubleAnimation anim1 = new DoubleAnimation(oldP.X, newP.X, TimeSpan.FromSeconds(0.2));
DoubleAnimation anim2 = new DoubleAnimation(oldP.Y, newP.Y , TimeSpan.FromSeconds(0.2));
target.BeginAnimation(Canvas.LeftProperty , anim1);
target.BeginAnimation(Canvas.TopProperty, anim2);
}
This code is based on #DeanChalk's answer.
It moves an Image contained within a Canvas (RFID_Token) diagonally from the top-right to the bottom-left, positioned centrally over another Image within a Canvas (RFID_Reader).
<Canvas>
<Canvas x:Name="RFID_Reader_Canvas">
<Image x:Name="RFID_Reader" Source="RFID-Reader.png" Height="456" Width="682" Canvas.Left="37" Canvas.Top="524"/>
</Canvas>
<Canvas x:Name="RFID_Token_Canvas">
<Image x:Name="RFID_Token" Source="RFID-Token.png" Height="268" Width="343" Canvas.Left="874" Canvas.Top="70"/>
</Canvas>
</Canvas>
var StartX = Canvas.GetLeft(RFID_Token);
var StartY = Canvas.GetTop(RFID_Token);
var EndX = RFID_Reader.Width / 2 + Canvas.GetLeft(RFID_Reader) - StartX - (RFID_Token.Width / 2);
var EndY = RFID_Reader.Height / 2 + Canvas.GetTop(RFID_Reader) - StartY - (RFID_Token.Height / 2);
var AnimationX = new DoubleAnimation(0, EndX, TimeSpan.FromSeconds(1));
var AnimationY = new DoubleAnimation(0, EndY, TimeSpan.FromSeconds(1));
var Transform = new TranslateTransform();
RFID_Token_Canvas.RenderTransform = Transform;
Transform.BeginAnimation(TranslateTransform.XProperty, AnimationX);
Transform.BeginAnimation(TranslateTransform.YProperty, AnimationY);
I kept having NaN or 0 values for my nested elements, here's a modified version of Danny's answer :
public void MoveTo(Canvas canvas, FrameworkElement target, FrameworkElement destination)
{
Point oldPoint = target.TransformToAncestor(canvas).Transform(new Point(0, 0));
Point newPoint = destination.TransformToAncestor(canvas).Transform(new Point(0, 0));
var EndX = destination.Width / 2 + newPoint.X - oldPoint.X - (target.Width / 2);
var EndY = destination.Height / 2 + newPoint.Y - oldPoint.Y - (target.Height / 2);
TranslateTransform trans = new TranslateTransform();
target.RenderTransform = trans;
DoubleAnimation anim1 = new DoubleAnimation(0, EndX, TimeSpan.FromSeconds(0.3));
DoubleAnimation anim2 = new DoubleAnimation(0, EndY, TimeSpan.FromSeconds(0.3));
trans.BeginAnimation(TranslateTransform.XProperty, anim1);
trans.BeginAnimation(TranslateTransform.YProperty, anim2);
}
I am trying to programmatically add bezier paths to a canvas in a WPF window. This works fine if I write them out in XAML, but adding one programmatically fails
XAML
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="320" Width="480" ContentRendered="Window_ContentRendered">
<Canvas Margin="10" Name="canvas">
<Rectangle Width="50" Height="100" Fill="LightSalmon" Margin="0,50"></Rectangle>
</Canvas>
</Window>
Code behind
private void Window_ContentRendered(object sender, EventArgs e)
{
var r = new Rectangle();
r.Width = 50;
r.Height = 50;
r.StrokeThickness = 3;
r.Fill = new SolidColorBrush(Colors.Black);
canvas.Children.Add(r);
//bezier is a System.Windows.Shapes.Path
bezier.Stroke = new SolidColorBrush(Colors.Black);
bezier.StrokeThickness = 35;
PathFigure pf = new PathFigure { StartPoint = new Point(50, 67.5) };
PolyBezierSegment pbs = new PolyBezierSegment(new Point[] { new Point(100, 67.5), new Point(100, 50), new Point(150, 50) }, false);
pf.Segments.Add(pbs);
PathFigureCollection pfc = new PathFigureCollection { pf };
PathGeometry pg = new PathGeometry();
pg.Figures = pfc;
bezier.Data = pg;
canvas.Children.Add(bezier);
canvas.Dispatcher.Invoke(() => { }, DispatcherPriority.Render);
}
Since the black rectangle is added correctly it must be something with building up the bezier path, but I can't figure out where the problem is. There are no errors or exceptions. It just doesn't show up on re-rendering.
For completeness, here the (currently commented out) XAML of the bezier, that works
<Path Stroke="Black" StrokeThickness="30" Name="blackPath">
<Path.Data>
<PathGeometry>
<PathFigureCollection>
<PathFigure StartPoint="50,67.5">
<PolyBezierSegment Points="100,67.5 100,50 150,50" />
</PathFigure>
</PathFigureCollection>
</PathGeometry>
</Path.Data>
</Path>
Problem solved
PolyBezierSegment pbs = new PolyBezierSegment(
new Point[] { new Point(100, 67.5),
new Point(100, 50),
new Point(150, 50) },
false); // <== Wrong
should be
PolyBezierSegment pbs = new PolyBezierSegment(
new Point[] { new Point(100, 67.5),
new Point(100, 50),
new Point(150, 50) },
true); // <== Set to true if the Stroke is defined separately, which is the case for me
is there any equivalent for System.Drawing.Drawing2D.GraphicsPath.AddArc, in Xaml UWP rendering ?
I have tried the below use case in XAML UWP up-to my knowledge.
Path path = new Path();
PathGeometry pathGeometry = new PathGeometry();
PathFigure pathFigure = new PathFigure();
ArcSegment arcSegment = new ArcSegment();
arcSegment.IsLargeArc = true;
arcSegment.Size = new Windows.Foundation.Size(100, 100);
arcSegment.Point = new Windows.Foundation.Point(100, 100);
arcSegment.RotationAngle = 180;
arcSegment.SweepDirection = SweepDirection.Clockwise;
pathFigure.StartPoint = new Windows.Foundation.Point(100, 100);
pathFigure.Segments.Add(arcSegment);
path.Data = pathGeometry;
path.Fill = new SolidColorBrush(Colors.Red);
path.StrokeThickness = 2;
pathGeometry.Figures.Add(pathFigure);
But the above is not 100% equivalent to System.Drawing.Drawing2D.GraphicsPath.AddArc(Rectangle, Single, Single)
is there any equivalent for System.Drawing.Drawing2D.GraphicsPath.AddArc, in Xaml UWP rendering ?
In classical windows form application, we have System.Drawing.Drawing2D namespace for drawing graphics. But this namespace is not supported in UWP app. UWP app has its own APIs for drawing graphics. You should be able to draw shapes by APIs under Windows.UI.Xaml.Shapes namespace. More details about how to draw shapes on uwp app please reference this article.
The method System.Drawing.Drawing2D.GraphicsPath.AddArc is actually for drawing a arc, which you already found in uwp app you could use adding ArcSegment instead.
But the above is not 100% equivalent to System.Drawing.Drawing2D.GraphicsPath.AddArc(Rectangle, Single, Single)
UWP app has its own APIs for drawing that it may not have a method that has same method name and same parameters as it in windows form. But you should be able to use other methods in uwp to implement the same effects. For example, the AddArc method has three parameters, Rectangle is for defined the x-diameter and y-diameter and the shape location, and startAngle and sweepAngle for defined the start and end angle. In uwp app, the ArcSegment can define the arc x-radius and y-radius by size property, and point for define start and end location.
For example, in a windows form, we may use the following code drawing a arc;
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
// Create a GraphicsPath object.
GraphicsPath myPath = new GraphicsPath();
// Set up and call AddArc, and close the figure.
Rectangle rect = new Rectangle(20, 20, 50, 100);
myPath.StartFigure();
myPath.AddArc(rect, 0, 180);
myPath.CloseFigure();
// Draw the path to screen.
e.Graphics.DrawPath(new Pen(Color.Red, 3), myPath);
}
In uwp app you can do the same thing in xaml by the following code:
<Path StrokeThickness="2" Margin="40,40,0,0" Stroke="Red">
<Path.Data>
<PathGeometry>
<PathFigure IsClosed="True">
<PathFigure.Segments>
<PathSegmentCollection>
<ArcSegment Size="25,50" Point="50,0" IsLargeArc="True" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
Or code behind:
private void btnCreatepath_Click(object sender, RoutedEventArgs e)
{
Path path = new Path();
PathGeometry pathGeometry = new PathGeometry();
PathFigure pathFigure = new PathFigure();
ArcSegment arcSegment = new ArcSegment();
arcSegment.IsLargeArc = true;
arcSegment.Size = new Windows.Foundation.Size(25, 50);
arcSegment.Point = new Windows.Foundation.Point(50, 0);
arcSegment.RotationAngle = 180;
pathFigure.IsClosed = true;
pathFigure.Segments.Add(arcSegment);
path.Data = pathGeometry;
path.Stroke = new SolidColorBrush(Colors.Red);
path.StrokeThickness = 2;
path.Margin = new Thickness(40, 40, 0, 0);
pathGeometry.Figures.Add(pathFigure);
gridroot.Children.Add(path);
}
And the result:
In a word that you should be able find APIs to draw the same thing which you done in the form.
i found a link in msdn to draw a shape in .XAML file, but how to do the same with c#, drawing a shape with c# in wp7 in silverlight without use xna?
I think this http://www.windowsphonegeek.com/tips/drawing-in-wp7-1-getting-started-and-line-shape will help you to draw shapes using C#.
Your XAML:
<Canvas x:Name="ContentPanelCanvas" Grid.Row="1" Background="Transparent" Margin="12,0,12,0">
<Line X1="10" Y1="100" X2="150" Y2="100" Stroke="Green" StrokeThickness="5"/>
</Canvas>
C#:
Line line = new Line();
line.Stroke = new SolidColorBrush(Colors.Purple);
line.StrokeThickness = 15;
Point point1 = new Point();
point1.X = 10.0;
point1.Y = 100.0;
Point point2 = new Point();
point2.X = 150.0;
point2.Y = 100.0;
line.X1 = point1.X;
line.Y1 = point1.Y;
line.X2 = point2.X;
line.Y2 = point2.Y;
this.ContentPanelCanvas.Children.Add(line);
Im trying to rotate a <Image> of an arrow (placed in the middle of a 40x40 image). By what I remember from graphics class i need to first translate the image back to its center, rotate and then translate back:
TranslateTransform tTrans = new TranslateTransform();
tTrans.X -= 20;
tTrans.X -= 20;
RotateTransform rTrans = new RotateTransform();
rTrans.Angle = 60;
TranslateTransform t2Trans = new TranslateTransform();
tTrans.X += 20;
tTrans.X += 20;
imgWind.RenderTransform = ?;
Anyone got a good idea on how i can apply the transformations?
You can simply use
imgWind.RenderTransform = new RotateTransform(){ CenterX = 0.5, CenterY = 0.5, Angle = 45 };
Or in XAML:
<UIElement RenderTransformOrigin="0.5,0.5">
<UIElement.RenderTransform>
<RotateTransform CenterX="0.5" CenterY="0.5" Angle="45" />
</UIElement.RenderTransform>
</UIElement>
By setting the CenterX and CenterY you don't have to translate before and after. In WPF (or silverlight for that matter) the transforms will take care of that themselfs.