在WPF中的网格中的单元格之间拖放自定义控件 [英] Drag and Drop custom controls between cells in a grid in WPF

查看:111
本文介绍了在WPF中的网格中的单元格之间拖放自定义控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些自定义控件被动态添加到自定义网格。这些控件可以跨越多个列和行(大小相同)。我想在行和列之间拖放。我可以拖动单个控件,但是它们可以随意移动,而不受任何限制。甚至离开电网。我想这样做,所以它只能被拖动到网格内并且捕捉到被拖动到的列/行。



有没有什么简单的方法呢?老实说,如果我能够获得当前的行/列,那么我需要做的就是将列/行设置为它们,那么可能会这样做,然后只是担心保持在网格内。

解决方案

我想出了一个很好玩的方式!



我制定了鼠标在MouseUp事件上的网格上的位置,然后鼠标在控件上的相对位置,因为它跨越了几行/列。

  public void getPosition(UIElement element,out int col,out int row)
{
DControl control = parent作为DCControl;
var point = Mouse.GetPosition(element);
row = 0;
col = 0;
double accumHeight = 0.0;
double accumWidth = 0.0;

// calc row mouse over
foreach(var rowDefinition in control.RowDefinitions)
{
accumHeight + = rowDefinition.ActualHeight;
if(cumulativeHeight> = point.Y)
break;
row ++;
}

// calc col mouse was over
foreach(var columnDefinition in control.ColumnDefinitions)
{
accumWidth + = columnDefinition.ActualWidth;
if(accumulationWidth> = point.X)
break;
col ++;
}
}

然后我从正常位置拿走相对位置所以当你把它放下时,它总是在屏幕的左上角。当我移动我的控件时,我使用边距来移动它,这时拧紧了网格上的位置,如下所示:

  void Chart_PreviewMouseMove(object sender,MouseEventArgs e)
{
if(IsMouseCaptured)
{
点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();
}

我希望这有助于别人,因为我很沮丧地找到答案,最后我设法得到了很多关于如何做事情的小碎片,最终想出了我自己的解决方案。


I've got some custom controls which are dynamically added to a custom grid. These controls can span over several columns and rows(which are all the same size). I'd like to drag and drop between the rows and columns. I can drag the individual controls, but they can move anywhere without limit. Even off the grid. I'd like to do it so it can only be dragged inside the grid AND snaps to the column/row it's dragged to.

Is there any easy-ish way to do this?

Honestly, if I could get the current row/column that it's over, then all I'd need to do is set the column/row of it to them and that would probably do it and then just worry about keeping it inside the grid.

解决方案

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.

这篇关于在WPF中的网格中的单元格之间拖放自定义控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆