Reputation: 39
I've got a simple UserControl placed in a Canvas on a Window control. I've attached events to MouseDown, MouseUp, and MouseMove in order for me to drag the control around the Canvas. I've attempted using PreviewMouseDown, PreviewMouseUp, and PreviewMouseMove as well but get the same result.
This part works but there is an annoying behavior of the UserControl shifting such that the Upper Left corner of it (point 0,0) is moved to the cursor location as soon as I click the UserControl. Code below is limited to what I think is essential to this issue.
Window.xaml
<Window x:Class="DragNDropBetweenControls.MainWindow"
xmlns:local="clr-namespace:DragNDropBetweenControls"
Title="MainWindow" MinHeight="350" MinWidth="525">
<Canvas>
<local:UserControl2/>
</Canvas>
</Window>
UserControl.xaml
<UserControl x:Class="DragNDropBetweenControls.UserControl2" >
<Canvas Background="AntiqueWhite">
<Grid Height="25" Width="100" AllowDrop="True" Name="B2"
MouseDown="B2_OnMouseDown"
MouseUp="B2_OnMouseUp"
MouseMove="ui2_MouseMove" >
<Rectangle Fill="Aqua" />
<TextBlock Text="Move Control" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Grid>
</Canvas>
</UserControl>
UserControl.xaml.cs
public partial class UserControl2 : UserControl
{
private bool IsMouseDown = false;
public UserControl2()
{
InitializeComponent();
}
private void B2_OnMouseDown(object sender, MouseButtonEventArgs e)
{
UIElement ui = (UIElement)sender;
IsMouseDown = true;
ui.CaptureMouse();
}
void ui2_MouseMove (object sender, MouseEventArgs e)
{
Grid b = (Grid)sender;
if (!IsMouseDown)
return;
UIElement parent = (UIElement)b.Parent;
Canvas.SetLeft(b, e.GetPosition(parent).X);
Canvas.SetTop(b, e.GetPosition(parent).Y);
e.Handled = true;
}
private void B2_OnMouseUp(object sender, MouseButtonEventArgs e)
{
IsMouseDown = false;
UIElement ui = (UIElement)sender;
ui.ReleaseMouseCapture();
e.Handled = true;
}
}
So what I want is for the cursor and control to stay at their same positions relative to each other when clicked and throughout the move process.
You thoughts/help are greatly appreciated!
Upvotes: 0
Views: 271
Reputation: 45
This will Work Im sure:
private bool IsMouseDown = false;
Point CPos;
private void B2_OnMouseDown(object sender, MouseButtonEventArgs e)
{
UIElement ui = (UIElement)sender;
IsMouseDown = true;
ui.CaptureMouse();
CPos = e.GetPosition(ui);
}
void ui2_MouseMove (object sender, MouseEventArgs e)
{
Grid b = (Grid)sender;
if (!IsMouseDown)
return;
UIElement parent = (UIElement)b.Parent;
Canvas.SetLeft(b, Mouse.GetPosition(parent).X - CPos.X);
Canvas.SetTop(b, Mouse.GetPosition(parent).Y - CPos.Y);
e.Handled = true;
}
private void B2_OnMouseUp(object sender, MouseButtonEventArgs e)
{
IsMouseDown = false;
UIElement ui = (UIElement)sender;
ui.ReleaseMouseCapture();
e.Handled = true;
}
Upvotes: 1
Reputation: 1555
This might help:
public partial class UserControl2 : UserControl
{
bool _pinned;
Point _offset;
public UserControl2()
{
InitializeComponent();
}
private void B2_OnMouseDown(object sender, MouseButtonEventArgs e)
{
var control = (UIElement)sender;
control.CaptureMouse();
_offset = e.GetPosition(control);
_pinned = true;
}
private void ui2_MouseMove(object sender, MouseEventArgs e)
{
if (!_pinned)
return;
var control = (FrameworkElement)sender;
var parent = (FrameworkElement)control.Parent;
Canvas.SetLeft(control, e.GetPosition(parent).X - _offset.X);
Canvas.SetTop(control, e.GetPosition(parent).Y - _offset.Y);
e.Handled = true;
}
private void B2_OnMouseUp(object sender, MouseButtonEventArgs e)
{
_pinned = false;
var control = (UIElement)sender;
control.ReleaseMouseCapture();
e.Handled = true;
}
}
Disclaimer: I haven't even tried to compile it. Sorry about that, but hopefully you get the idea.
Upvotes: 2