In _MouseMove
, you're trying to calculate the movement using e.GetPosition(this)
, but that only gets the mouse pointer position relative to your Grid
. You need to find the position relative to some other UI element, e.g. the containing Window
in order to know how much the grid should move.
Try e.GetPosition(null)
(that is null instead of this) in both _MouseLeftButtonDown
and _MouseMove
to calculate correct delta
s.
This article illustrates the difference: Getting the Mouse Position Relative to a Specific Element
EDIT: More robust FloatingPanel
:
In the constructor, avoid having a gadget that may end up on top of the title bar by putting them in two separate RowDefinition
s (and let WPF handle widths and heights):
public FloatingPanel(FrameworkElement gadget)
{
gridTitle = new Grid();
gridTitle.Height = 25;
gridTitle.Background = Brushes.Cyan;
gridTitle.MouseLeftButtonDown += gridTitle_MouseLeftButtonDown;
gridTitle.MouseMove += gridTitle_MouseMove;
gridTitle.MouseLeftButtonUp += gridTitle_MouseLeftButtonUp;
//Create two grid rows - one to hold the title bar..
this.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
Grid.SetRow(gridTitle, 0);
this.Children.Add(gridTitle);
//..and one two hold the gadget:
this.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
Grid.SetRow(gadget, 1);
this.Children.Add(gadget);
}
In the ..ButtonDown
/..ButtonUp
handlers, make the title bar "capture" (and release) the mouse movements so the mouse pointer doesn't "slide off" when moving too fast:
void gridTitle_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
//Relese a previous capture:
Mouse.Capture(null);
dragging = false;
}
void gridTitle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
lastPos = Mouse.GetPosition(null);
//Capture the mouse to ensure we get all future mouse movements:
Mouse.Capture(gridTitle);
dragging = true;
}
EDIT 2: Alternative without Mouse.Capture()
:
...
gridTitle.MouseLeftButtonDown += gridTitle_MouseLeftButtonDown;
//gridTitle.MouseMove += gridTitle_MouseMove;
//The parent Window isn't available yet here in the constructor,
//so we must wait for our Loaded event to hook it up:
this.Loaded += (s, e) => { Window.GetWindow(this).MouseMove += gridTitle_MouseMove; };
gridTitle.MouseLeftButtonUp += gridTitle_MouseLeftButtonUp;
...