放大或缩小时WPF拖动列表框

时间:2017-10-09 15:26:55

标签: c# wpf canvas listbox

我有一个WPF项目(C#,MVVM,Visual Studio 2010)。

有一个ListBox,其中有项目。如果玩家使用单击并拖动来重新定位它们,则可以自由移动项目(ItemsPanelTemplate是Canvas控件)。

它工作正常,但我也有一个使用鼠标滚轮的放大和缩小方法。

问题是,在放大或缩小状态下,如果拖动一个ListBoxItem,它就不能正常工作。不知怎的,坐标看起来有点偏差。

这是鼠标滚轮方法:

void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        lastMousePositionOnTarget = Mouse.GetPosition(NodeDragCanvas);

        if (e.Delta > 0)
        {
            if (dScaleValue < dZoomMax)
                dScaleValue += dZoomIncrementValue;
        }
        if (e.Delta < 0)
        {
            if(dScaleValue > dZoomMin)
                dScaleValue -= dZoomIncrementValue;
        }

        e.Handled = true;

        scaleTransform.ScaleX = dScaleValue;
        scaleTransform.ScaleY = dScaleValue;

        var centerOfViewport = new Point(NodeDragScrollViewer.ViewportWidth / 2, NodeDragScrollViewer.ViewportHeight / 2);
        lastCenterPositionOnTarget = NodeDragScrollViewer.TranslatePoint(centerOfViewport, NodeDragCanvas);
    }

当然还需要鼠标移动方法:

void OnMouseMove(object sender, MouseEventArgs e)
    {
        if (lastDragPoint.HasValue)
        {
            Point posNow = e.GetPosition(NodeDragScrollViewer);

            double dX = (posNow.X - lastDragPoint.Value.X);// *this.dScaleValue;
            double dY = (posNow.Y - lastDragPoint.Value.Y);// *this.dScaleValue;

            lastDragPoint = posNow;

            // This situation is a drag.
            if (LbNodes.SelectedItems.Count == 0)
            {
                NodeDragScrollViewer.ScrollToHorizontalOffset(NodeDragScrollViewer.HorizontalOffset - dX);
                NodeDragScrollViewer.ScrollToVerticalOffset(NodeDragScrollViewer.VerticalOffset - dY);
            }
            else
            {
                // This situation is mouse drag of items
                foreach (ChatNodeViewModel cv in LbNodes.SelectedItems)
                {
                    cv.XCoord += dX;
                    cv.YCoord += dY;
                }

                // This bit just causes the lines between the nodes to update.
                Mediator.EventMediator.Instance.RefreshAllNodesDraggable();
            }
        }
    }

正如您可能看到的那样,我试图通过将dX和dY乘以比例值来稍微摸索它。它似乎没有用。

或多解释一下。好吧,假设我们有一个只是图像的ListBoxItem。在正常(默认)缩放级别,您可以单击此项并移动它。移动它时,鼠标光标停留在相对于ListBoxItem的相同位置。在缩放状态下,它会四处漂移,甚至可能会离开ListBoxItem。显然,应该在哪里和基于缩放级别的位置之间存在某种关系,但我不知道它是什么。

我不知道这里是否有标准的解决方案,但我当然希望得到一些指导。

感谢。

1 个答案:

答案 0 :(得分:0)

好吧,如果我找到了解决方案(我做了),那么良好的互联网礼仪就会回复。

我玩了几个想法...但我似乎没有意识到的主要原因是对dX和dY应用任何更改也适用于缩放(因为它用于和鼠标拖动)。

所以我创建了两个独立的变量(dMouseDragX和dMouseDragY)来进行实验。我尝试的第一件事,因为我意识到如果我放大则漂移更大,而如果我缩小则更少,是创建dScaleValue变量的替代品,当dScale值减小时增加,并且当dScaleValue减少时增加。这让我更接近,但不足以称之为成功。尽管如此,我还是走在正确的轨道上 - 这是我需要的dScaleValue的一些反面。然后......好吧......我使用了倒数。它奏效了。

所以MouseMove现在看起来像这样:

void OnMouseMove(object sender, MouseEventArgs e)
    {
        if (lastDragPoint.HasValue)
        {
            Point posNow = e.GetPosition(NodeDragScrollViewer);

            double dX = (posNow.X - lastDragPoint.Value.X);
            double dY = (posNow.Y - lastDragPoint.Value.Y);

            // This was a bit of a guess, but it seems to work like a charm.
            double dMouseDragX = (posNow.X - lastDragPoint.Value.X) * (1/dScaleValue);
            double dMouseDragY = (posNow.Y - lastDragPoint.Value.Y) * (1/dScaleValue);


            lastDragPoint = posNow;

            // This situation is a drag.
            if (LbNodes.SelectedItems.Count == 0)
            {
                NodeDragScrollViewer.ScrollToHorizontalOffset(NodeDragScrollViewer.HorizontalOffset - dX);
                NodeDragScrollViewer.ScrollToVerticalOffset(NodeDragScrollViewer.VerticalOffset - dY);
            }
            else
            {
                // This situation is mouse drag of items
                foreach (ChatNodeViewModel cv in LbNodes.SelectedItems)
                {
                    cv.XCoord += dMouseDragX;
                    cv.YCoord += dMouseDragY;
                }

                // This bit just causes the lines between the nodes to update.
                Mediator.EventMediator.Instance.RefreshAllNodesDraggable();
            }
        }
    }

所以它几乎一样,但是反向应用于鼠标拖动......就是这样!