I figured out a nice and fun way!
I worked out the position on the grid that the the mouse is on on the MouseUp event and then the relative position of the mouse on the control since it spans several rows/columns.
public void getPosition(UIElement element, out int col, out int row)
{
DControl control = parent as DControl;
var point = Mouse.GetPosition(element);
row = 0;
col = 0;
double accumulatedHeight = 0.0;
double accumulatedWidth = 0.0;
// calc row mouse was over
foreach (var rowDefinition in control.RowDefinitions)
{
accumulatedHeight += rowDefinition.ActualHeight;
if (accumulatedHeight >= point.Y)
break;
row++;
}
// calc col mouse was over
foreach (var columnDefinition in control.ColumnDefinitions)
{
accumulatedWidth += columnDefinition.ActualWidth;
if (accumulatedWidth >= point.X)
break;
col++;
}
}
I then take away the relative positions from the normal positions so that when you drop it, it always drops on the top left of the screen. When I move my controls, I use margins to move it, which screws up the position on the grid at the time, as shown below:
void Chart_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (IsMouseCaptured)
{
Point mouseDelta = Mouse.GetPosition(this);
mouseDelta.Offset(-mouseOffset.X, -mouseOffset.Y);
Margin = new Thickness(
Margin.Left + mouseDelta.X,
Margin.Top + mouseDelta.Y,
Margin.Right - mouseDelta.X,
Margin.Bottom - mouseDelta.Y);
}
}
void Chart_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
mouseOffset = Mouse.GetPosition(this);
CaptureMouse();
parent.currentObject = this;
}
To tackle this, I simply reset the margin.
public void updatePosition()
{
Grid.SetRow(this, (int)position.Y);
Grid.SetColumn(this, (int)position.X);
Margin = new Thickness();
}
I hope this helps someone else since it was rather frustrating for me to find the answer and in the end I managed to get lots of little fragments of how to do things and eventually came up with my own solution.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…