I have added the following parameters to my Window:
WindowStyle="None"
WindowStartupLocation="CenterScreen"
AllowsTransparency="True"
ResizeMode="NoResize" Background="Transparent"
And now I can't move the Window, so I have added the following part of code to my Window:
#region Window: Moving
private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DragMove();
}
#endregion
Also I must specify that my XAML code in my Window is the following (the Window look like the Polygon):
<Window Title="New Science"
Height="588" Width="760" MinHeight="360" MinWidth="360"
WindowStyle="None" WindowStartupLocation="CenterScreen"
AllowsTransparency="True"
ResizeMode="NoResize" Background="Transparent"
xmlns:my="clr-namespace:Bourlesque.Lib.Windows.Media;assembly=Bourlesque.Lib.Windows.Media">
<Grid>
<my:UniPolygon DefaultRadiusIn="10" DefaultRadiusOut="10" Fill="#FF92C2F2" Name="m_tPlgOuter" Offset="0" Points=" 0;26;; 10;19;10;; 10;0;; 265;0;20;; 290;20;20;; -60,1;20;3;; -60,1;5;10;; -40,1;5;10;; -40,1;20;2.5;; -35,1;20;2.5;; -35,1;5;10;; -15,1;5;10;; -15,1;20;3;; 0,1;20;; 0,1;0,1;; 0;0,1;; " Stretch="None" Stroke="#FF535353" StrokeThickness="0.1" />
</Grid>
</Window>
I would like to know what should I do to make the Window change it's position on mouse drag and what to add to resize the window with the condition that the controls and other things I will add will resize too(I have found this code to resize and I would like to know if is good here).
I used the event MouseDown:
<Window .....
MouseDown="Window_MouseDown" >
with this code:
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if(e.ChangedButton == MouseButton.Left)
this.DragMove();
}
Found a example:
http://cloudstore.blogspot.com.br/2008/06/moving-wpf-window-with-windowstyle-of.html
Anyway, to move a Window in WinForms I used in a project the following code, can be useful if you are having problems:
private bool clicado = false;
private Point lm = new Point();
void PnMouseDown(object sender, MouseEventArgs e)
{
clicado = true;
this.lm = MousePosition;
}
void PnMouseUp(object sender, MouseEventArgs e)
{
clicado = false;
}
void PnMouseMove(object sender, MouseEventArgs e)
{
if(clicado)
{
this.Left += (MousePosition.X - this.lm.X);
this.Top += (MousePosition.Y - this.lm.Y);
this.lm = MousePosition;
}
}
I've tried another solution and worked (not sure if it is the most correct though)
private void GridOfWindow_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var move = sender as System.Windows.Controls.Grid;
var win = Window.GetWindow(move);
win.DragMove();
}
where GridOfWindow is the name of the Grid
<Grid x:Name="GridOfWindow" MouseLeftButtonDown="GridOfWindow_MouseLeftButtonDown">
good code to the answer, but buggy. it will get your moving out of control.
try my modify:
private bool clicado = false;
private Point lm = new Point();
void PnMouseDown(object sender, System.Windows.Input.MouseEventArgs e)
{
clicado = true;
this.lm = System.Windows.Forms.Control.MousePosition;
this.lm.X = Convert.ToInt16(this.Left) - this.lm.X;
this.lm.Y = Convert.ToInt16(this.Top) - this.lm.Y;
}
void PnMouseUp(object sender, System.Windows.Input.MouseEventArgs e)
{
clicado = false;
}
void PnMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if (clicado)
{
this.Left = (System.Windows.Forms.Control.MousePosition.X + this.lm.X);
this.Top = (System.Windows.Forms.Control.MousePosition.Y + this.lm.Y);
}
}
it will get your moving stick to your cursor.(///▽///)
#Marcio there is no Windows.Forms in WPF.
I got this version to work (steady) with WPF,
private bool clicked = false;
private Point lmAbs = new Point();
void PnMouseDown(object sender, System.Windows.Input.MouseEventArgs e)
{
clicked = true;
this.lmAbs = e.GetPosition(this);
this.lmAbs.Y = Convert.ToInt16(this.Top) + this.lmAbs.Y;
this.lmAbs.X = Convert.ToInt16(this.Left) + this.lmAbs.X;
}
void PnMouseUp(object sender, System.Windows.Input.MouseEventArgs e)
{
clicked = false;
}
void PnMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if (clicked)
{
Point MousePosition = e.GetPosition(this);
Point MousePositionAbs = new Point();
MousePositionAbs.X = Convert.ToInt16(this.Left) + MousePosition.X;
MousePositionAbs.Y = Convert.ToInt16(this.Top) + MousePosition.Y;
this.Left = this.Left + (MousePositionAbs.X - this.lmAbs.X);
this.Top = this.Top + (MousePositionAbs.Y - this.lmAbs.Y);
this.lmAbs = MousePositionAbs;
}
}
Kind regards,
Lex
I had to fix above's a bit to work properly... working as charm now! Use this with: MouseLeftButtonDown at your main Window.
private void EnableDrag(object sender, MouseButtonEventArgs e)
{
var move = sender as Window;
if (move != null)
{
Window win = Window.GetWindow(move);
win.DragMove();
}
}
Related
While looking for ways to drag around a UIElement in WPF I came across some code and have been experimenting with it. When the Element is clicked, it nicely follows the mouse, but on a subsequent drag-event, the Element reset itself to its original position.
The xaml setup: Very simple, just a named Canvas with the most original name ever and the Element, in this case a grid, called Tile1.
<Grid>
<Canvas x:Name="Canvas" Width="200" Height="300" Background="LightGray">
<Grid x:Name="Tile1">
<Border BorderBrush="Black" BorderThickness="1" Background="White">
<Control Width="25" Height="25"/>
</Border>
</Grid>
</Canvas>
</Grid>
some code-behind:
public TranslateTransform transPoint;
public Point originPoint;
public MainWindow()
{
InitializeComponent();
Tile1.MouseLeftButtonDown += Tile1_MouseLeftButtonDown;
Tile1.MouseLeftButtonUp += Tile1_MouseLeftButtonUp;
Tile1.MouseMove += Tile1_MouseMove;
}
private void Tile1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var myLocation = e.GetPosition(Canvas);
originPoint = new Point(myLocation.X, myLocation.Y);
transPoint = new TranslateTransform(originPoint.X, originPoint.Y);
}
private void Tile1_MouseMove(object sender, MouseEventArgs e)
{
var mouseLocation = e.GetPosition(Canvas);
if (e.LeftButton == MouseButtonState.Pressed)
{
transPoint.X = (mouseLocation.X - originPoint.X);
transPoint.Y = (mouseLocation.Y - originPoint.Y);
Tile1.RenderTransform = transPoint;
}
}
private void Tile1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
var mouseLocationOnCanvas = e.GetPosition(Canvas);
var mouseLocationOnTile = e.GetPosition(Tile1);
//attempting to account for offset of mouse on the Tile:
var newX = mouseLocationOnCanvas.X - mouseLocationOnTile.X;
var newY = mouseLocationOnCanvas.Y - mouseLocationOnTile.Y;
Tile1.Margin = new Thickness(newX, newY, 0, 0);
}
In the original example (reference added here) A MouseUpEvent wasn't even used. Without it, my element just resets to its original position at 0,0 at every MouseDragEvent. And with it, it'll jump all over the place.
My train of thought was to somehow set the Element's current position to where the MouseUpEvent occurred.
I've been fiddling around with different things, as this particular stuff is rather new to me. Examples are: Tile1.TransformToAncestor(Canvas).Transform(mouseLocation);
I also found that VisualOffset has the information I need, so somehow it's already stored on the object, before being reset, but I haven't found a way to access it in any form.
Tile1.SetValue(VisualOffset.X = ...); or Tile1Grid.GetValue(VisualOffset);
So basically, is there a way to not have the element reset its position after RenderTransform?
I didn't find MouseLeftButtonDown event useful so I removed it:
I noticed some lags when moving the mouse that ould be annoying maybe the event needs to run asynchronously MouseMove performance slow using GetPosition.
public TranslateTransform transPoint = new TranslateTransform(0, 0);
public Point originPoint = new Point(0, 0);
public MainWindow()
{
InitializeComponent();
Tile1.MouseLeftButtonUp += Tile1_MouseLeftButtonUp;
Tile1.MouseMove += Tile1_MouseMove;
}
private void Tile1_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
var mouseLocation = e.GetPosition(Canvas);
transPoint.X = (mouseLocation.X - originPoint.X);
transPoint.Y = (mouseLocation.Y - originPoint.Y);
Tile1.RenderTransform = transPoint;
}
}
private void Tile1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
var mouseLocation = e.GetPosition(Tile1);
originPoint.X = mouseLocation.X;
originPoint.Y = mouseLocation.Y;
}
The RenderTransform seems to erratic, but I got the UIElement to stay put after moving it using the following:
private void MovableTile_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
tile.CaptureMouse();
}
with
private void MovableTile_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
var tile = sender as UIElement;
var mousePosition = e.GetPosition(canvas);
Canvas.SetLeft(tile, mousePosition.X);
Canvas.SetTop(tile, mousePosition.Y);
}
}
and then
private void MovableTile_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
tile.ReleaseMouseCapture();
}
The MouseCapture was the key here. :)
I'm trying to figure out if there's an elegant solution to the problem I've been faced with.
So basically, I designed a borderless loading splash screen which is completely movable via dragging. I find that this happens if the splash screen gets hidden via Hide(), then displays a window via ShowDialog() with the owner set to the splash screen. Things get extremely buggy, but only if you're in mid-drag (with left mouse button down). You become unable to click or move anything, even Visual Studio becomes unresponsive unless you explicitly alt-tab out of the application.
Considering I know when I'm going to spawn the window, I was thinking maybe there'd be a way to cancel the DragMove operation, but I'm having no luck. What I've figured out is that DragMove is synchronous, so I'd guess it'd have to be cancelled from a different thread or in an event callback.
Edit:
public partial class Window_Movable : Window
{
public Window_Movable()
{
InitializeComponent();
}
public Boolean CanMove { get; set; } = true;
private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (CanMove == false)
return;
Task.Factory.StartNew(() => {
System.Threading.Thread.Sleep(1000);
Dispatcher.Invoke(() => {
Hide();
new Window_Movable() {
Title = "MOVABLE 2",
CanMove = false,
Owner = this
}.ShowDialog();
});
});
DragMove();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("DING");
}
}
I had the same problem and found out that DragMove() method is a problem.
https://groups.google.com/forum/#!topic/wpf-disciples/7OcuXrf2whc
To solve I decided to refuse from using it and implement moving logic.
I've combined some solutions from
https://www.codeproject.com/Questions/284995/DragMove-problem-help-pls
and
C# WPF Move the window
private bool _inDrag;
private Point _anchorPoint;
private bool _iscaptured;
private void AppWindowWindowOnMouseMove(object sender, MouseEventArgs e)
{
if (!_inDrag)
return;
if (!_iscaptured)
{
CaptureMouse();
_iscaptured = true;
}
var mousePosition = e.GetPosition(this);
var mousePositionAbs = new Point
{
X = Convert.ToInt16(_appWindowWindow.Left) + mousePosition.X,
Y = Convert.ToInt16(_appWindowWindow.Top) + mousePosition.Y
};
_appWindowWindow.Left = _appWindowWindow.Left + (mousePositionAbs.X - _anchorPoint.X);
_appWindowWindow.Top = _appWindowWindow.Top + (mousePositionAbs.Y - _anchorPoint.Y);
_anchorPoint = mousePositionAbs;
}
private void AppWindowWindowOnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (_inDrag)
{
_inDrag = false;
_iscaptured = false;
ReleaseMouseCapture();
}
}
private void AppWindowWindowOnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_anchorPoint = e.GetPosition(this);
_anchorPoint.Y = Convert.ToInt16(_appWindowWindow.Top) + _anchorPoint.Y;
_anchorPoint.X = Convert.ToInt16(_appWindowWindow.Left) + _anchorPoint.X;
_inDrag = true;
}
I've spend all yesterday evening and find a more hacky but more functional solution. Which support Maximized state and not require manual coordinate calculation.
private bool _mRestoreForDragMove;
private void OnAppWindowWindowOnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 2)
{
if (_appWindowWindow.ResizeMode != ResizeMode.CanResize &&
_appWindowWindow.ResizeMode != ResizeMode.CanResizeWithGrip)
{
return;
}
_appWindowWindow.WindowState = _appWindowWindow.WindowState == WindowState.Maximized
? WindowState.Normal
: WindowState.Maximized;
}
else
{
_mRestoreForDragMove = _appWindowWindow.WindowState == WindowState.Maximized;
SafeDragMoveCall(e);
}
}
private void SafeDragMoveCall(MouseEventArgs e)
{
Task.Delay(100).ContinueWith(_ =>
{
Dispatcher.BeginInvoke((Action)
delegate
{
if (Mouse.LeftButton == MouseButtonState.Pressed)
{
_appWindowWindow.DragMove();
RaiseEvent(new MouseButtonEventArgs(e.MouseDevice, e.Timestamp, MouseButton.Left)
{
RoutedEvent = MouseLeftButtonUpEvent
});
}
});
});
}
private void OnMouseMove(object sender, MouseEventArgs e)
{
if (_mRestoreForDragMove)
{
_mRestoreForDragMove = false;
var point = PointToScreen(e.MouseDevice.GetPosition(this));
_appWindowWindow.Left = point.X - (_appWindowWindow.RestoreBounds.Width * 0.5);
_appWindowWindow.Top = point.Y;
_appWindowWindow.WindowState = WindowState.Normal;
_appWindowWindow.DragMove();
SafeDragMoveCall(e);
}
}
private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
_mRestoreForDragMove = false;
}
The thing is to send LeftMouseButtonUp event after a short delay to avoid blocking from DragMove()
Sources for last solve:
DragMove() and Maximize
C# WPF - DragMove and click
And one more completely different solution. To make a window movable you can use CaptionHeight of WindowChrome.
i.e.
var windowChrome =
WindowChrome.GetWindowChrome(appWindow.Window);
windowChrome.CaptionHeight = MainWindowToolbar.Height;
WindowChrome.SetWindowChrome(appWindow.Window, windowChrome);
but you should also set attached property WindowChrome.IsHitTestVisibleInChrome="True" for all controls in the window.
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;
}
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;
Having trouble with something here which I'm hoping is actually simple.
I have a custom UserControl in WPF which allows me to display an image. When the program is running a user can add this UserControl as many times as they like to a canvas. In effect a simple image viewer where they can add and move images about.
I would like to be able to right click these images open a contextMenu and then choose send backward of bring forward and the images would then change z order depending which menu choice was clicked.
I have the user control set up with the contextMenu so I just need to know the code for changing the z order of this userControl...
Any help is much appreciated :)
namespace StoryboardTool
{
/// <summary>
/// Interaction logic for CustomImage.xaml
/// </summary>
public partial class CustomImage : UserControl
{
private Point mouseClick;
private double canvasLeft;
private double canvasTop;
public CustomImage()
{
InitializeComponent();
cusImageControl.SetValue(Canvas.LeftProperty, 0.0);
cusImageControl.SetValue(Canvas.TopProperty, 0.0);
}
public void chooseImage()
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Title = "Choose Image to Add";
if (ofd.ShowDialog() == true)
{
BitmapImage bImage = new BitmapImage();
bImage.BeginInit();
bImage.UriSource = new Uri(ofd.FileName);
bImage.EndInit();
image.Width = bImage.Width;
image.Height = bImage.Height;
image.Source = bImage;
image.Stretch = Stretch.Fill;
}
}
private void cusImageControl_LostMouseCapture(object sender, MouseEventArgs e)
{
((CustomImage)sender).ReleaseMouseCapture();
}
private void cusImageControl_MouseUp(object sender, MouseButtonEventArgs e)
{
((CustomImage)sender).ReleaseMouseCapture();
cusImageControl.Cursor = Cursors.Arrow;
}
private void cusImageControl_MouseMove(object sender, MouseEventArgs e)
{
if ((((CustomImage)sender).IsMouseCaptured) && (cusImageControl.Cursor == Cursors.SizeAll))
{
Point mouseCurrent = e.GetPosition(null);
double Left = mouseCurrent.X - mouseClick.X;
double Top = mouseCurrent.Y - mouseClick.Y;
mouseClick = e.GetPosition(null);
((CustomImage)sender).SetValue(Canvas.LeftProperty, canvasLeft + Left);
((CustomImage)sender).SetValue(Canvas.TopProperty, canvasTop + Top);
canvasLeft = Canvas.GetLeft(((CustomImage)sender));
canvasTop = Canvas.GetTop(((CustomImage)sender));
}
else if ((((CustomImage)sender).IsMouseCaptured) && (cusImageControl.Cursor == Cursors.SizeNWSE))
{
/*Point mouseCurrent = e.GetPosition(null);
cusImageControl.Height = cusImageControl.canvasTop + mouseClick.Y;
cusImageControl.Width = cusImageControl.canvasLeft + mouseClick.X;
mouseClick = e.GetPosition(null);*/
}
}
private void cusImageControl_MouseDown(object sender, MouseButtonEventArgs e)
{
mouseClick = e.GetPosition(null);
canvasLeft = Canvas.GetLeft(((CustomImage)sender));
canvasTop = Canvas.GetTop(((CustomImage)sender));
((CustomImage)sender).CaptureMouse();
}
private void ContextMenuBringForward_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Bring Forward");
}
private void ContextMenuSendBackward_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Send Backward");
}
private void ContextMenuMove_Click(object sender, RoutedEventArgs e)
{
cusImageControl.Cursor = Cursors.SizeAll;
}
private void ContextMenuResize_Click(object sender, RoutedEventArgs e)
{
cusImageControl.Cursor = Cursors.SizeNWSE;
}
}
}
See Panel attached property Canvas.SetZIndex. Change z-Index of all elements to 0, and z-Index of your right-clicked control to 1.
void mouseUp(object sender, MouseButtonEventArgs e)
{
foreach (var child in yourCanvas.Children) Canvas.SetZIndex(child, 0);
Canvas.SetZIndex((UIElement)sender, 1);
}
The following code works where selected is defined as my UserControl and set in the mouseDown event.
private void ContextMenuSendBackward_Click(object sender, RoutedEventArgs e)
{
Canvas parent = (Canvas)LogicalTreeHelper.GetParent(this);
foreach (var child in parent.Children)
{
Canvas.SetZIndex((UIElement)child, 0);
}
Canvas.SetZIndex(selected, 1);
}
Thanks to voo for all his help.