I'm C# newbie. I want to access my Canvas in MainPage.xaml from class CS_Line, but i can't do it. How to call the name's canvas in class CS_Line.cs.
MainPage.xaml:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Canvas x:Name="MyCanvas" HorizontalAlignment="Left" Height="573" Margin="154,76,0,0" VerticalAlignment="Top" Width="913" Background="White"/>
</Grid>
in CS_Line.cs:
class CS_Line
{
//attribute
InkManager _inkKhaled = new Windows.UI.Input.Inking.InkManager();
private uint _penID;
private uint _touchID;
private Point _previousContactPt;
private Point currentContacPt;
private double x1;
private double y1;
private double x2;
private double y2;
//method
private void MyCanvas_PointerPressed(object sender, PointerRoutedEventArgs e)
{
PointerPoint pt = e.GetCurrentPoint(MyCanvas); *//====>>>>> can't access the MyCanvas*
_previousContactPt = pt.Position;
PointerDeviceType pointerDevType = e.Pointer.PointerDeviceType;
if (pointerDevType == PointerDeviceType.Pen ||
pointerDevType == PointerDeviceType.Mouse &&
pt.Properties.IsLeftButtonPressed)
{
_inkKhaled.ProcessPointerDown(pt);
_penID = pt.PointerId;
e.Handled = true;
}
else if (pointerDevType == PointerDeviceType.Touch)
{
}
}
You can get MyCanvas from sender.
private void MyCanvas_PointerPressed(object sender, PointerRoutedEventArgs e)
{
Canvas myCanvas = sender as Canvas; // Here's your MyCanvas object
PointerPoint pt = e.GetCurrentPoint(myCanvas);
_previousContactPt = pt.Position;
Related
I want to draw area inside a container. For this i thought about using custom control.
My problem is that Canvas does not take up all the given space it gets. How to force it to use all available space?
What i have done is inherited from Canvas and created border element inside it:
public class DrawableCanvas : Canvas
{
private Border border;
static DrawableCanvas()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(DrawableCanvas), new FrameworkPropertyMetadata(typeof(DrawableCanvas)));
}
public DrawableCanvas()
{
this.border = new Border();
border.Background = new SolidColorBrush(Colors.Blue);
border.BorderThickness = new Thickness(1);
border.Width = 0;
border.Visibility = Visibility.Hidden;
border.Opacity = 0.3;
this.Children.Add(border);
this.MouseLeftButtonDown += DrawableCanvas_MouseLeftButtonDown;
this.MouseLeftButtonUp += DrawableCanvas_MouseLeftButtonUp;
this.MouseMove += DrawableCanvas_MouseMove;
}
private void DrawableCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("Left mouse up");
// release mouse
Mouse.Capture(null);
border.Width = 0;
border.Height = 100;
startPosition = 0;
}
double startPosition = 0;
private void DrawableCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("Left mouse down");
border.Visibility = Visibility.Visible;
// capture mouse
Mouse.Capture(this);
var point = e.GetPosition(this);
startPosition = point.X;
SetLeft(border, point.X);
}
private void DrawableCanvas_MouseMove(object sender, MouseEventArgs e)
{
if(this.IsMouseCaptured)
{
var point = e.GetPosition(this);
Debug.WriteLine("Mouse move");
// set the position to far left
SetLeft(border, Math.Min(startPosition, point.X));
// width is the difference between two points
border.Width = Math.Abs(startPosition - point.X);
Debug.WriteLine(Math.Min(startPosition, point.X));
Debug.WriteLine(border.Width);
}
}
}
And for view:
<DockPanel>
<local:DrawableCanvas>
<Rectangle Height="500" Width="500" Fill="Transparent" />
</local:DrawableCanvas>
</DockPanel>
I want something like this:
What I wanted to do is to create this control to enable selection on ui.
For this i needed a border/rectangle that will span only in width and use up all the height it gets
I ended up with this:
View:
<Window x:Class="Wpf.Test01.Stack_43281567"
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:Wpf.Test01.Controls"
mc:Ignorable="d"
Title="Stack_43281567" Height="300" Width="300">
<Grid>
<local:DrawableCanvas />
</Grid>
</Window>
DrawableCanvas.cs:
public class DrawableCanvas : Canvas
{
private Border border;
static DrawableCanvas()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(DrawableCanvas), new FrameworkPropertyMetadata(typeof(DrawableCanvas)));
}
// when selection is done expose event to notify the user of selection change
public DrawableCanvas()
{
this.border = new Border();
border.Background = new SolidColorBrush(Colors.Blue);
border.BorderThickness = new Thickness(1);
border.Visibility = Visibility.Hidden;
border.Opacity = 0.3;
border.Height = this.ActualHeight;
this.Children.Add(border);
this.Background = new SolidColorBrush(Colors.Transparent);
this.MouseLeftButtonDown += DrawableCanvas_MouseLeftButtonDown;
this.MouseLeftButtonUp += DrawableCanvas_MouseLeftButtonUp;
this.MouseMove += DrawableCanvas_MouseMove;
this.SizeChanged += DrawableCanvas_SizeChanged;
}
private void DrawableCanvas_SizeChanged(object sender, SizeChangedEventArgs e)
{
border.Height = e.NewSize.Height;
}
private void DrawableCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("Left mouse up");
// release mouse
Mouse.Capture(null);
border.Width = 0;
startPosition = 0;
}
double startPosition = 0;
private void DrawableCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("Left mouse down");
border.Visibility = Visibility.Visible;
// capture mouse
Mouse.Capture(this);
var point = e.GetPosition(this);
startPosition = point.X;
SetLeft(border, point.X);
}
private void DrawableCanvas_MouseMove(object sender, MouseEventArgs e)
{
if (this.IsMouseCaptured)
{
var point = e.GetPosition(this);
Debug.WriteLine("Mouse move");
// set the position to far left
SetLeft(border, Math.Min(startPosition, point.X));
// width is the difference between two points
border.Width = Math.Abs(startPosition - point.X);
Debug.WriteLine(Math.Min(startPosition, point.X));
Debug.WriteLine(border.Width);
}
}
}
I want to move the label by using the Mouse_Move/Mouse_Down events.
I tried to do it like this:
private void control_MouseDown(object sender, MouseButtonEventArgs e)
{
Label l = e.Source as Label;
if (l != null)
{
l.CaptureMouse();
moving = true;
PositionInLabel = e.GetPosition(l);
}
}
private void control_MouseMove(object sender, MouseEventArgs e)
{
if (moving)
{
Point p = e.GetPosition(null);
DeltaX = p.X - BasePoint.X - PositionInLabel.X;
DeltaY = p.Y - BasePoint.Y - PositionInLabel.Y;
RaisePropertyChanged("XPosition");
RaisePropertyChanged("YPosition");
}
}
Suppose your label is on a Canvas:
public MainWindow()
{
InitializeComponent();
this.label.MouseLeftButtonDown += control_MouseLeftButtonDown;
this.label.MouseMove += control_MouseMove;
this.label.MouseLeftButtonUp += control_MouseLeftButtonUp;
}
// Keep track of the Canvas where this element is placed.
private Canvas canvas;
// Keep track of when the element is being dragged.
private bool isDragging = false;
// When the element is clicked, record the exact position
// where the click is made.
private Point mouseOffset;
private void control_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Label l = e.Source as Label;
if (l == null)
return;
// Find the Canvas.
if (canvas == null)
canvas = (Canvas)VisualTreeHelper.GetParent(l);
// Dragging mode begins.
isDragging = true;
// Get the position of the click relative to the element
// (so the top-left corner of the element is (0,0).
mouseOffset = e.GetPosition(l);
// Capture the mouse. This way you'll keep receiving
// the MouseMove event even if the user jerks the mouse
// off the element.
l.CaptureMouse();
}
private void control_MouseMove(object sender, MouseEventArgs e)
{
Label l = e.Source as Label;
if (l == null)
return;
if (isDragging)
{
// Get the position of the element relative to the Canvas.
Point point = e.GetPosition(canvas);
// Move the element.
l.SetValue(Canvas.TopProperty, point.Y - mouseOffset.Y);
l.SetValue(Canvas.LeftProperty, point.X - mouseOffset.X);
}
}
private void control_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
Label l = e.Source as Label;
if (l == null)
return;
if (isDragging)
{
l.ReleaseMouseCapture();
isDragging = false;
}
}
Let containerCanvas be a Canvas which contains the Label; then you can utilize the _MouseMove(object sender, MouseEventArgs e) to move the label along with your mouse pointer:
Xaml code:
<Canvas Name="containerCanvas" MouseMove="containerCanvas_MouseMove" Background="Aqua" Width="525" Height="350" >
<Label Name="floatingLabel" Height="28" Width="161" Background="AliceBlue"></Label>
</Canvas>
C# code:
private void containerCanvas_MouseMove(object sender, MouseEventArgs e)
{
Point p = Mouse.GetPosition(Application.Current.MainWindow);
floatingLabel.Margin = new Thickness(p.X, p.Y, 0, 0);
}
I have done a sample code. Check this. It should work.
XAML :
<UserControl HorizontalAlignment="Left" x:Class="WPFDiagramDesignerControl.Components.TestApp"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="100" Width="100" IsEnabled="True">
<Grid >
<Canvas x:Name="MyDesigner">
<TextBox x:Name="txtBox" IsEnabled="True" Background="AntiqueWhite" Margin="10,10,10,10" TextWrapping="Wrap"> </TextBox>
</Canvas>
</Grid>
Code Behind :
public TestApp()
{
InitializeComponent();
txtBox.MouseDoubleClick+=new MouseButtonEventHandler(control_MouseDoubleClick);
txtBox.MouseMove+=new MouseEventHandler(control_MouseMove);
txtBox.PreviewMouseDown+=new MouseButtonEventHandler(control_PreviewMouseDown);
txtBox.PreviewMouseUp+=new MouseButtonEventHandler(control_PreviewMouseUp);
txtBox.Cursor = Cursors.SizeAll;
}
private void control_MouseMove(object sender, RoutedEventArgs e)
{
if (isClicked)
{
Point mousePos = Mouse.GetPosition(parentCanvas);
parentItem = this.Parent as DesignerItem;
parentCanvas = parentItem.Parent as DesignerCanvas;
Point relativePosition = Mouse.GetPosition(parentCanvas);
DesignerCanvas.SetLeft(this, DesignerCanvas.GetLeft(this) - (startPoint.X - mousePos.X));
DesignerCanvas.SetTop(this, DesignerCanvas.GetTop(this) - (startPoint.Y - mousePos.Y));
}
}
private void control_PreviewMouseDown(object sender, RoutedEventArgs e)
{
if (!isClicked)
{
isClicked = true;
parentItem = this.Parent as DesignerItem;
parentCanvas = parentItem.Parent as DesignerCanvas;
startPoint = Mouse.GetPosition(parentCanvas);
}
}
private void control_PreviewMouseUp(object sender, RoutedEventArgs e)
{
isClicked = false;
}
I have these three functions to trigger the events. I already have a static version of my needs, but I need a dynamically version of it.
bool captured = false;
double x_shape, x_canvas, y_shape, y_canvas;
UIElement source = null;
private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
source = (UIElement)sender;
Mouse.Capture(source);
captured = true;
x_shape = Canvas.GetLeft(source);
x_canvas = e.GetPosition(canvasPreview).X;
y_shape = Canvas.GetTop(source);
y_canvas = e.GetPosition(canvasPreview).Y;
}
private void MouseMove(object sender, MouseEventArgs e)
{
//MessageBox.Show("test");
if (captured)
{
double x = e.GetPosition(canvasPreview).X;
double y = e.GetPosition(canvasPreview).Y;
x_shape += x - x_canvas;
Canvas.SetLeft(source, x_shape);
x_canvas = x;
y_shape += y - y_canvas;
Canvas.SetTop(source, y_shape);
y_canvas = y;
}
}
private void MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
Mouse.Capture(null);
captured = false;
}
I have made a canvas in WPF called 'canvasPreview', I want to add the rectangle (currently in the static version I am using an ellipse) to the canvas, it must be draggable with above functions. It is already working, but it have to be dynamically.
I hope you can help me, thank you in advance!
I'm sure this sample code will help you.
XAML:
<Grid Margin="12">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal">
<Button x:Name="addRectangleButton" Content="Add Rectngle" Click="addRectangleButton_Click"/>
</StackPanel>
<Canvas Grid.Row="1" x:Name="canvas" Margin="0,12,0,0">
<Rectangle x:Name="rectangle" Width="100" Height="50" Fill="RoyalBlue" MouseDown="rectangle_MouseDown" MouseMove="rectangle_MouseMove" MouseUp="rectangle_MouseUp" Canvas.Left="0" Canvas.Top="0"/>
</Canvas>
</Grid>
C#:
bool drag = false;
Point startPoint;
public MainWindow()
{
InitializeComponent();
}
// this creates and adds rectangles dynamically
private void addRectangleButton_Click(object sender, RoutedEventArgs e)
{
// create new Rectangle
Rectangle rectangle = new Rectangle();
// assign properties
rectangle.Width = 100;
rectangle.Height = 50;
rectangle.Fill = new SolidColorBrush(Colors.RoyalBlue);
// assign handlers
rectangle.MouseDown += rectangle_MouseDown;
rectangle.MouseMove += rectangle_MouseMove;
rectangle.MouseUp += rectangle_MouseUp;
// set default position
Canvas.SetLeft(rectangle, 0);
Canvas.SetTop(rectangle, 0);
// add it to canvas
canvas.Children.Add(rectangle);
}
private void rectangle_MouseDown(object sender, MouseButtonEventArgs e)
{
// start dragging
drag = true;
// save start point of dragging
startPoint = Mouse.GetPosition(canvas);
}
private void rectangle_MouseMove(object sender, MouseEventArgs e)
{
// if dragging, then adjust rectangle position based on mouse movement
if (drag)
{
Rectangle draggedRectangle = sender as Rectangle;
Point newPoint = Mouse.GetPosition(canvas);
double left = Canvas.GetLeft(draggedRectangle);
double top = Canvas.GetTop(draggedRectangle);
Canvas.SetLeft(draggedRectangle, left + (newPoint.X - startPoint.X));
Canvas.SetTop(draggedRectangle, top + (newPoint.Y - startPoint.Y));
startPoint = newPoint;
}
}
private void rectangle_MouseUp(object sender, MouseButtonEventArgs e)
{
// stop dragging
drag = false;
}
I'm trying to move a rectangle drawn in Canvas by mouse (drag and drop).
When I click on the Rectangle and move the mouse (keep clicking) to a new position it's OK:
But when I click on it again and move the mouse just a bit the Rectangle move to old position:
I don't know why it is. Can anybody give me some explaination?
Here is my code (all parameters have been assigned and initialized).
Thanks in advance!
private void MyCanvas_MouseMove_1(object sender, MouseEventArgs e)
{
if (e.RightButton == MouseButtonState.Pressed && e.OriginalSource is Shape)
{
p2 = e.GetPosition(MyCanvas);
TranslateTransform tf = new TranslateTransform(p2.X - p1.X, p2.Y - p1.Y);
_MyTestRect.RenderTransform = tf;
}
}
private void MyCanvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.OriginalSource is Shape)
{
p1 = e.GetPosition(MyCanvas);
}
}
Mvvm Behavior Approach add the refference to:
System.Windows.Interactivity.
In XAML:
<Canvas x:Name="MyCanvas" Background="#00FFFFFF">
<i:Interaction.Behaviors>
<!--soSandBox is the reffrence to the behavior-->
<soSandBox:MoveElementsInCanvasBehavior/>
</i:Interaction.Behaviors>
<Rectangle x:Name="_MyTestRect1" Fill="Tomato" Width="50" Height="50"/>
<Rectangle x:Name="_MyTestRect2" Fill="Tomato" Width="50" Height="50"/>
<Rectangle x:Name="_MyTestRect3" Fill="Tomato" Width="50" Height="50"/></Canvas>
Behavior code:
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.MouseLeftButtonDown += AssociatedObjectOnMouseLeftButtonDown;
AssociatedObject.MouseLeftButtonUp += AssociatedObjectOnMouseLeftButtonUp;
AssociatedObject.MouseMove += AssociatedObjectOnMouseMove;
}
private void AssociatedObjectOnMouseMove(object sender, MouseEventArgs e)
{
if (_shape != null && _shape.IsMouseCaptured)
{
_p2 = e.GetPosition(AssociatedObject);
_shape.SetValue(Canvas.TopProperty, _p2.Y - _originalOffsetFromTop);
_shape.SetValue(Canvas.LeftProperty, _p2.X - _originalOffsetFromLeft);
}
}
private void AssociatedObjectOnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (_shape == null) return;
_shape.ReleaseMouseCapture();
_shape = null;
}
private double GetDist(double originalValue, double newValue)
{
if (double.IsNaN(originalValue) || double.IsInfinity(originalValue))
return Math.Abs(newValue - 0);
return Math.Abs(newValue - originalValue);
}
private void AssociatedObjectOnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_shape = e.OriginalSource as Shape;
if (_shape != null)
{
_p1 = e.GetPosition(AssociatedObject);
_shape.CaptureMouse();
_originalOffsetFromTop = GetDist((double)_shape.GetValue(Canvas.TopProperty), _p1.Y);
_originalOffsetFromLeft = GetDist((double)_shape.GetValue(Canvas.LeftProperty), _p1.X);
}
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.MouseLeftButtonDown -= AssociatedObjectOnMouseLeftButtonDown;
AssociatedObject.MouseLeftButtonUp -= AssociatedObjectOnMouseLeftButtonUp;
AssociatedObject.MouseMove -= AssociatedObjectOnMouseMove;
}
Summary:
This way you can put inside the canvas as much elements as you wish, and when you click the element (and when this element is a shape) you will be able to move it.
Translate Transform XAML:
<Canvas x:Name="MyCanvas" Background="#00FFFFFF">
<i:Interaction.Behaviors>
<!--convert event to command mechanism-->
<soSandBox:CanvasMouseEventObservingBehavior
OnMouseMoveAction="{Binding OnMouseMoveAction, UpdateSourceTrigger=PropertyChanged}"
OnMouseRightButtonDownAction="{Binding OnMouseRightButtonDownAction, UpdateSourceTrigger=PropertyChanged}"
OnMouseRightButtonUpAction="{Binding OnMouseRightButtonUpAction, UpdateSourceTrigger=PropertyChanged}"/>
</i:Interaction.Behaviors>
<Rectangle x:Name="_MyTestRect1" Fill="Tomato" Width="50" Height="50">
<Rectangle.RenderTransform>
<TransformGroup>
<TranslateTransform X="{Binding TranslateTransformX, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
Y="{Binding TranslateTransformY, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"></TranslateTransform>
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle></Canvas>
Translate Transform view model (translation related code):
private void RightMouseUp(Point obj)
{
_originalPoint = obj;
_currentOffsetByX = GetDist(_currentOffsetByX, obj.X);
_currentOffsetByY = GetDist(_currentOffsetByY, obj.Y);
}
private void RightMouseDown(Point obj)
{
_originalPoint = obj;
_currentOffsetByX = GetDist(_currentOffsetByX, obj.X);
_currentOffsetByY = GetDist(_currentOffsetByY, obj.Y);
}
private void MouseMoved(Point obj)
{
TranslateTransformX = obj.X - _currentOffsetByX;
TranslateTransformY = obj.Y - _currentOffsetByY;
}
private double GetDist(double originalValue, double newValue)
{
if (double.IsNaN(originalValue) || double.IsInfinity(originalValue))
return Math.Abs(newValue - 0);
return Math.Abs(newValue - originalValue);
}
public double TranslateTransformY
{
get { return _translateTransformY; }
set
{
_translateTransformY = value;
OnPropertyChanged();
}
}
public double TranslateTransformX
{
get { return _translateTransformX; }
set
{
_translateTransformX = value;
OnPropertyChanged();
}
}
Regards
You should not create the transform every time otherwise you reset the translation.
Create a TranslateTransform if none exist.
Then cumulate the translations inside.
Regards
Try just using the Canvas.SetTop and Canvas.SetLeft.
Rectangle myRectangle = new Rectangle();
myRectangle += myRectangle_MouseLeftButtonDown;
void myRectangle_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
myRectangle.MouseMove += origin_MouseMove;
}
void myRectangle_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
Point p = new Point()
{
// Just round the coordinates
X = Math.Round(e.GetPosition(canvas).X, 0, MidpointRounding.AwayFromZero),
Y = Math.Round(e.GetPosition(canvas).Y, 0, MidpointRounding.AwayFromZero),
};
Canvas.SetTop(myRectangle, p.Y);
Canvas.SetLeft(myRectangle, p.X);
myRectangle.MouseLeftButtonUp += myRectangle_MouseLeftButtonUp;
}
void myRectangle_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
myRectangle.MouseMove -= origin_MouseMove;
myRectangle.MouseLeftButtonUp -= origin_MouseLeftButtonUp;
}
How move ellipse by mouse on window in WPF.
private void ellipse_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
Ellipse ellipse = sender as Ellipse;
if (ellipse != null && e.LeftButton == MouseButtonState.Pressed)
{
DragDrop.DoDragDrop(ellipse,
ellipse.Fill.ToString(),
System.Windows.DragDropEffects.Copy);
}
}
How to create method ellipse_MouseClick?
There is no MouseClick event on Ellipses, however there is the MouseDown and MouseUp events. I assume you are looking for something like this.
WPF:
<Window x:Class="WpfApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="350" Width="525"
MouseMove="Any_MouseMove"
>
<Canvas>
<Ellipse Fill="Lavender" Height="100" Width="100"
MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"
MouseLeftButtonUp="Ellipse_MouseLeftButtonUp"
MouseMove="Any_MouseMove" />
</Canvas>
</Window>
Code Behind:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace WpfApplication
{
public partial class MainWindow : Window
{
private UIElement _lastClickedUIElement;
private Point? _clickOffset;
public MainWindow() { InitializeComponent(); }
private void Ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_lastClickedUIElement = sender as UIElement;
_clickOffset = e.GetPosition(_lastClickedUIElement);
}
private void Ellipse_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
_lastClickedUIElement = null;
}
private void Any_MouseMove(object sender, MouseEventArgs e)
{
if (_lastClickedUIElement == null)
return;
_lastClickedUIElement.SetValue(Canvas.LeftProperty, e.GetPosition(this).X - _clickOffset.Value.X);
_lastClickedUIElement.SetValue(Canvas.TopProperty, e.GetPosition(this).Y - _clickOffset.Value.Y);
}
}
}
Click on the circle to move it around. This will work on any UI element as long as long as you give them those methods. feel free to add a Rectangle to the canvas also.
<Rectangle Fill="Lavender" Height="100" Width="100"
MouseLeftButtonDown="Ellipse_MouseLeftButtonDown"
MouseLeftButtonUp="Ellipse_MouseLeftButtonUp"
MouseMove="Any_MouseMove" />
I use three events to accomplish this task:
XAML:
<Window x:Class="WpfPainting.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="500" Width="700" WindowStartupLocation="CenterScreen">
<DockPanel>
<Canvas Background="White" Name="CanvasArea"/>
</DockPanel>
</Window>
Code:
private UIElement source;
private bool captured;
double x_shape, x_canvas, y_shape, y_canvas;
private void ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Mouse.OverrideCursor = Cursors.SizeAll;
source = (UIElement)sender;
Mouse.Capture(source);
captured = true;
x_shape = Canvas.GetLeft(source);
x_canvas = e.GetPosition(CanvasArea).X;
y_shape = Canvas.GetTop(source);
y_canvas = e.GetPosition(CanvasArea).Y;
}
private void ellipse_MouseMove(object sender, MouseEventArgs e)
{
if (captured)
{
double x = e.GetPosition(CanvasArea).X;
double y = e.GetPosition(CanvasArea).Y;
x_shape += x - x_canvas;
Canvas.SetLeft(source, x_shape);
x_canvas = x;
y_shape += y - y_canvas;
Canvas.SetTop(source, y_shape);
y_canvas = y;
}
}
private void ellipse_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
Mouse.Capture(null);
captured = false;
Mouse.OverrideCursor = null;
}
To use the events on a painted ellipse I refer to them like this:
ellipse.MouseLeftButtonDown += conveyor_MouseLeftButtonDown;
ellipse.MouseMove += conveyor_MouseMove;
ellipse.MouseLeftButtonUp += conveyor_MouseLeftButtonUp;