I am trying to make a UserControl that drags across the canvas. I am using C# and WPF. I see many examples across the net, but I just need the bare minimum.
I found an article: "Draggable Control in WPF"
Someone responded with:
If you want to do it by hands use following algorithm:
On MouseDown event: Save Mouse position, TopLeft position of control, and delta(offset) of these coordinates, and set some boolean field flag eg. IsDragStartted to true. On MouseMove check that drag started and use Mouse position and offset to calculate the new value of TopLeft position of control
On MouseUp event set IsDragStarted to false
I am having trouble applying this.
public partial class UserControl1 : UserControl {
private Point startingMousePosition;
private Point endingMousePosition;
private Point startingControlPosition;
bool isDragStarted;
public UserControl1()
{
InitializeComponent();
}
private void Grid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if(!isDragStarted)
{
startingControlPosition.X = Canvas.GetLeft(this);
startingControlPosition.Y = Canvas.GetTop(this);
startingMousePosition.X = e.GetPosition(this.Parent as Canvas).X;
startingMousePosition.Y = e.GetPosition(this.Parent as Canvas).Y;
}
}
private void Grid_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
isDragStarted = true;
if (isDragStarted)
{
endingMousePosition.X = e.GetPosition(this.Parent as Canvas).X;
endingMousePosition.Y = e.GetPosition(this.Parent as Canvas).Y;
Canvas.SetLeft(this, endingMousePosition.X - startingControlPosition.X);
Canvas.SetTop(this, endingMousePosition.Y - startingControlPosition.Y);
}
}
}
private void Grid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
isDragStarted = false;
}
}
Here is my code for the Main Window WPF form:
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
UserControl1 userCTL;
public MainWindow()
{
InitializeComponent();
userCTL = new UserControl1();
userCTL.Width = 50;
userCTL.Height = 100;
Canvas.SetTop(userCTL,20);
Canvas.SetLeft(userCTL, 20);
CanvasMain.Children.Add(userCTL);
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
AdornerLayer myAdornerLayer = AdornerLayer.GetAdornerLayer(userCTL);
if (myAdornerLayer != null)
{
myAdornerLayer.Add(new SimpleCircleAdorner(userCTL));
}
}
}
}
Here is my WPF code for the main Window:
<Window x:Class="WpfApplicationEvent.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="374.306" Width="594.271" Loaded="Window_Loaded">
<Grid>
<ScrollViewer Margin="46,23,74,33" PanningMode="Both" HorizontalScrollBarVisibility="Visible">
<Canvas x:Name="CanvasMain" Height="395" Width="506">
</Canvas>
</ScrollViewer>
</Grid>
</Window>
I also tried placing adorners so I can eventually resize the control. that went nowhere as got the adorners but they don't do anything.
I have all my drag controls in my UserControl1 I created and I got it to drag, but when I click the UserControl1 instance again to drag it a second time it resets to the SetTop(0) and SetLeft (0) locations. It jumps there so weirdly!I was expecting the UserControl1 instance drag to the location of the cursor. It does it on the first try but then I click the UserControl1 to drag it one more time and it jumps to (0,0) or close to it.