我有一些自动控件可以动态添加到自定义网格中。这些控件可以跨越多个列和行(大小都相同)。我想在行和列之间拖放。我可以拖动各个控件,但是它们可以无限制地移动到任何地方。即使离开电网。我想这样做,所以它只能在网格内拖动并捕捉到它拖动到的列/行。
有没有简单易行的方法呢?
老实说,如果我能得到当前的行/列,那么我需要做的就是将它的列/行设置为它们,那可能会这样做,然后只是担心将其保留在里面网格。
答案 0 :(得分:4)
我想出了一个很好玩的方式!
我计算了MouseUp事件上鼠标所在的网格上的位置,然后是鼠标在控件上的相对位置,因为它跨越了几行/列。
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++;
}
}
然后我从正常位置拿走相对位置,这样当你放下它时,它总是落在屏幕的左上角。当我移动我的控件时,我使用边距来移动它,这会在当时拧紧网格上的位置,如下所示:
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;
}
要解决这个问题,我只需重置保证金。
public void updatePosition()
{
Grid.SetRow(this, (int)position.Y);
Grid.SetColumn(this, (int)position.X);
Margin = new Thickness();
}
我希望这可以帮助别人,因为找到答案让我感到非常沮丧,最后我设法得到了很多关于如何做事的小片段,最终想出了我自己的解决方案。
答案 1 :(得分:1)
有没有简单易行的方法呢?
我会说这个问题的答案很大程度上取决于你使用拖放功能的经验......对于一个初学者,我会说这个问题的答案是否定的,但是对于有经验的人来说一些常识,可能不会太糟糕。
确定用户鼠标所在的Grid
个单元格不会是直接的。您可以处理PreviewDragOver
事件并使用VisualTreeHelper.HitTest
method检查鼠标当前所在的控件:
private void PreviewDragOver(object sender, DragEventArgs e)
{
HitTestResult hitTestResult = VisualTreeHelper.HitTest(adornedUIElement,
e.GetPosition(adornedUIElement));
Control controlUnderMouse = hitTestResult.VisualHit.GetParentOfType<Control>();
}
GetParentOfType
方法是我创建的有用的扩展方法,但您可以轻松地将其转换为常规方法:
public static T GetParentOfType<T>(this DependencyObject element) where T : DependencyObject
{
Type type = typeof(T);
if (element == null) return null;
DependencyObject parent = VisualTreeHelper.GetParent(element);
if (parent == null && ((FrameworkElement)element).Parent is DependencyObject) parent = ((FrameworkElement)element).Parent;
if (parent == null) return null;
else if (parent.GetType() == type || parent.GetType().IsSubclassOf(type)) return parent as T;
return GetParentOfType<T>(parent);
}
当然,一旦你的Control
变量中有一个controlUnderMouse
,当你完成UIElement
之后,你仍然需要完成一些相当大的工作。到Grid
...您当然可以进一步使用GetParentOfType
方法来简化您的工作。