拖动一个WPF用户控件

7
我创建了一个可移动的UserControl
    <UserControl x:Class="Restaurant.Views.Managerer.TablePanel"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Restaurant.Helpers.Converter"
        mc:Ignorable="d"
        x:Name="root"
        MouseLeftButtonDown="root_MouseLeftButtonDown"
        MouseLeftButtonUp="root_MouseLeftButtonUp"
        MouseMove="root_MouseMove"    
        DataContext="{Binding RelativeSource={RelativeSource Self}}">
....

代码

Point anchorPoint;
        Point currentPoint;
        bool isInDrag = false;

        private void root_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var element = sender as FrameworkElement;
            anchorPoint = e.GetPosition(null);
            element.CaptureMouse();
            isInDrag = true;
            e.Handled = true;
        }

        private void root_MouseMove(object sender, MouseEventArgs e)
        {
            if (isInDrag)
            {
                var element = sender as FrameworkElement;
                currentPoint = e.GetPosition(null);

                var transform = new TranslateTransform
                                    {
                                        X = (currentPoint.X - anchorPoint.X),
                                        Y = (currentPoint.Y - anchorPoint.Y)
                                    };
                this.RenderTransform = transform;
                anchorPoint = currentPoint;
            }
        }

        private void root_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (isInDrag)
            {
                var element = sender as FrameworkElement;
                element.ReleaseMouseCapture();
                isInDrag = false;
                e.Handled = true;
            }
        }

如果我更改代码,从以下内容:

X = (currentPoint.X - anchorPoint.X),
Y = (currentPoint.Y - anchorPoint.Y)

to

X = (currentPoint.X),
Y = (currentPoint.Y)

我可以移动UserControl,但鼠标和UserControl不匹配。


5
@mazbsky - 没有问题,最后几个词可能暗示了一个问题,但语法不正确。 - Robert Levy
3个回答

17

早上好。我已经睡醒了,现在头脑清晰。

 private TranslateTransform transform = new TranslateTransform();
        private void root_MouseMove(object sender, MouseEventArgs e)
        {
            if (isInDrag)
            {
                var element = sender as FrameworkElement;
                currentPoint = e.GetPosition(null);

                transform.X += currentPoint.X - anchorPoint.X;
                transform.Y += (currentPoint.Y - anchorPoint.Y);
                this.RenderTransform = transform;
                anchorPoint = currentPoint;
            }
        }

1
不错,但这种方法并不是很高效。当拖动包含约10个自定义模板控件的网格时,我的CPU负载会上升到23%!(Core i7 3770)难道没有更好的方法吗?我还将父容器更改为画布并使用Canvas.SetLeft,但性能没有改变。 - SepehrM
我建议在鼠标移动时也使用rx节流来处理更少的事件。 - Eli Dagan
2
你如何防止控件越界?我开始使用这个方法来拖动控件,效果很好,但当用户到达边缘时,它会让控件超出窗口并变得不可见。 - Kevin B Burns

6

我真的不确定你在问题中想要实现什么,但拇指对于拖拽动作来说更容易。你可以在这里看到解释和示例代码(在底部)(链接)


链接已过期。还有关于此事的更多信息吗? - Harikrishnan N

-2

根据@Mediator的回答,我进行了修改以防止控件越界。

private TranslateTransform transform = new TranslateTransform();
    private void root_MouseMove(object sender, MouseEventArgs e)
    {
        if (isInDrag)
        {
            var element = sender as FrameworkElement;
            currentPoint = e.GetPosition(null);

            transform.X += currentPoint.X - anchorPoint.X;
            transform.Y += (currentPoint.Y - anchorPoint.Y);
            if (currentPoint.X < Application.Current.MainWindow.RenderSize.Width && currentPoint.Y < Application.Current.MainWindow.RenderSize.Height
                && currentPoint.X > 0 && currentPoint.Y > 0 )
            {
                this.RenderTransform = transform;
                anchorPoint = currentPoint;
            }
            else
            {
                transform = new TranslateTransform();
                this.RenderTransform = transform;
            }
        }
    }

但绑定错误在VS的输出窗口中存在。
看起来这是WPF中的问题,但微软不会修复它。
有关更多信息,请参见: https://connect.microsoft.com/VisualStudio/feedback/details/1423399/system-windows-data-error-4-when-using-relativesource-findancestor-inside-a-translatetransform-inside-a-style

这会导致容易避免的“跳动”行为。(例如,通过引用Thumb来避免。)此外,所谓的“错误”与问题毫无关系。 - Informagic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接