C# 在WPF中网格中的单元格之间拖放自定义控件

C# 在WPF中网格中的单元格之间拖放自定义控件,c#,wpf,drag-and-drop,grid,C#,Wpf,Drag And Drop,Grid,我有一些自定义控件,它们被动态添加到自定义网格中。这些控件可以跨多个列和行(大小都相同)。我想在行和列之间拖放。我可以拖动单个控件,但它们可以无限制地移动到任何地方。甚至在电网之外。我希望这样做,以便它只能在网格内拖动,并捕捉到它拖动到的列/行 有什么简单的方法可以做到这一点吗 老实说,如果我能得到当前结束的行/列,那么我所需要做的就是将它的列/行设置为它们,这可能会做到,然后只需要担心将它保留在网格中 有什么简单的方法可以做到这一点吗 我想说,这个问题的答案在很大程度上取决于您使用拖放功能的经

我有一些自定义控件,它们被动态添加到自定义网格中。这些控件可以跨多个列和行(大小都相同)。我想在行和列之间拖放。我可以拖动单个控件,但它们可以无限制地移动到任何地方。甚至在电网之外。我希望这样做,以便它只能在网格内拖动,并捕捉到它拖动到的列/行

有什么简单的方法可以做到这一点吗

老实说,如果我能得到当前结束的行/列,那么我所需要做的就是将它的列/行设置为它们,这可能会做到,然后只需要担心将它保留在网格中

有什么简单的方法可以做到这一点吗

我想说,这个问题的答案在很大程度上取决于您使用拖放功能的经验。。。对于初学者来说,我会说答案是否定的,但是对于一些有经验和常识的人来说,这可能并不太糟糕

要确定用户的鼠标在哪个网格上,不能直接向前移动。您可以处理
PreviewDragOver
事件,并使用检查鼠标当前位于哪个控件上:

private void PreviewDragOver(object sender, DragEventArgs e)
{
    HitTestResult hitTestResult = VisualTreeHelper.HitTest(adornedUIElement, 
        e.GetPosition(adornedUIElement));
    Control controlUnderMouse = hitTestResult.VisualHit.GetParentOfType<Control>();
}

当然,一旦在鼠标下的
controlUnderMouse
变量中有了
Control
,在到达
网格之前,在通过
UIElement
时,您仍然需要做大量的工作。。。当然,您可以进一步使用
GetParentOfType
方法来简化您的工作。

我想出了一个有趣的方法

我计算出鼠标在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();
    }

我希望这对其他人有所帮助,因为找到答案对我来说是相当令人沮丧的,最终我设法获得了很多关于如何做事的小片段,并最终提出了自己的解决方案

可能是这样的:?不过它们是任意的控件。虽然它们都是从同一事物中派生出来的。我需要更多信息,以便查看我将项目拖动到的行/列。我通过计算行高+列宽,直到鼠标到达鼠标点,从而获得鼠标在当前网格上的位置。然后,我计算出鼠标相对于控件左上角的相对位置,并将其从位置上取下,以便它将其指定给该位置。它得到了正确的值,但当我对项执行
Grid.SetRow(this,row)
操作时,同样地,使用
Grid.SetColumn
时,它会将它们放在一个随机位置。有什么原因吗?是因为它使用边距移动控件吗?嗯,是的。当我更新它们时,我重置了边距,效果非常好!我不知道为什么我要评论这个答案,因为我没有使用它的任何东西,但无论如何谢谢你的帮助!我不知道我为什么要评论这个答案。。。我也一样。将你的解决方案添加到答案中,并在可能的情况下接受它。对此表示抱歉!我已经这样做了,但不幸的是,我有几天不能接受它。WPF
ThumbControl
应该能够在没有
Margin
技巧的情况下处理这个问题,但它不能。“在使用
ThumbControl
s进行了无数个毫无结果的小时后,我终于走上了你的路,@Gentatsu。干得好,干得好。
parent
指的是什么?什么是
DControl
?您可以发布整个代码吗?在复制上有困难。
public void updatePosition()
    {
        Grid.SetRow(this, (int)position.Y);
        Grid.SetColumn(this, (int)position.X);
        Margin = new Thickness();
    }