防止滚动时拖放

3
我正在处理一个Wpf项目,但现在我卡在了ListView问题上。
事实证明,我已经在ListView上实现了一个良好的拖放功能。问题出现在我尝试向下或向上滚动时。这样做会激活拖放功能,导致我无法继续滚动。
我找到了此解决方案,它指出我们需要将我们的控件附加到ScrollChanged事件上。
<ListView ScrollViewer.ScrollChanged="listView1_ScrollChanged"...

但我真的不知道如何在该处理程序中做什么。 如何从该事件禁用拖放??如何再次启用它??或者,有更好的解决方法吗?

这是我的拖放代码:

 private void listView1_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        // Store the mouse position
        startPoint = e.GetPosition(null);
    }

    private void listView1_MouseMove(object sender, MouseEventArgs e)
    {
        // Get the current mouse position
        Point mousePos = e.GetPosition(null);
        Vector diff = startPoint - mousePos;

        if (e.LeftButton == MouseButtonState.Pressed &&
            (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
            Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
        {
            // Get the dragged ListViewItem
            ListView listView = sender as ListView;

            // Get items to drag
            var a = listView.SelectedItems;

            // Initialize the drag & drop operation
            DataObject dragData = new DataObject("myFormat", a);
            DragDrop.DoDragDrop(listView, dragData, DragDropEffects.Move);
        } 
    }

感谢您的提前帮助。

也许如果您能启发我们您是如何实现拖放功能的,那就太好了。 - Georgi-it
@Georgi-it 代码已添加。 - Dante
3个回答

0

如果你不在MouseDown事件中,可以防止MouseMove事件的发生:

bool stopDrag = true;
     private void listView1_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            // Store the mouse position
            startPoint = e.GetPosition(null);
stopDrag = false;
        }

        private void listView1_MouseMove(object sender, MouseEventArgs e)
        {
if(stopDrag)
   return;

            // Get the current mouse position
            Point mousePos = e.GetPosition(null);
            Vector diff = startPoint - mousePos;

            if (e.LeftButton == MouseButtonState.Pressed &&
                (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
                Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
            {
                // Get the dragged ListViewItem
                ListView listView = sender as ListView;

                // Get items to drag
                var a = listView.SelectedItems;

                // Initialize the drag & drop operation
                DataObject dragData = new DataObject("myFormat", a);
                DragDrop.DoDragDrop(listView, dragData, DragDropEffects.Move);
            } 
        }

private void listView1_MouseUp(...)
{
stopDrag = true;
}

这应该可以工作,我是在浏览器中编写的,如果我做错了什么或者格式不对,请原谅,希望你能理解我的意思。


嗨,我刚刚尝试了一下,但是它没有起作用,它一直表现得一样 :( - Dante
理论上它应该可以工作,也许如果你调试一下并给我一些额外的信息... - Georgi-it
我已经尝试过了,问题在于当我按下鼠标左键时,stopDrag 变成了 false,因此当它进入 listView1_MouseMove 方法时,条件 if(stopDrag) return 就不满足了。我可以反转这个条件,但这样做会导致 Drag&Drop 功能从未启动,因为我的 Drag&Drop 功能是在 PreviewMouseLeftButtonDown 事件中开始获取鼠标位置的。 - Dante

0

我使用一个简单的方法来确认拖动操作是否已确认,该方法使用了专门为此目的设计的SystemParameters.MinimumHorizontalDragDistanceSystemParameters.MinimumVerticalDragDistance

private bool IsDragConfirmed(Point point)
{
    bool horizontalMovement = Math.Abs(point.X - dragStartPosition.X) > 
         SystemParameters.MinimumHorizontalDragDistance;
    bool verticalMovement = Math.Abs(point.Y - dragStartPosition.Y) > 
         SystemParameters.MinimumVerticalDragDistance;
    return (horizontalMovement | verticalMovement);
}

PreviewMouseMove 事件中调用... 这里是一个简化的示例:

private void DragSourcePreviewMouseMove(object sender, MouseEventArgs e)
{
    if (isMouseDown && IsDragConfirmed(e.GetPosition(sender as ListBox)))
    {
        // Start your drag operation here
    }
}

0
我遇到了与下面答案中相同的问题和源代码。 我决定如果鼠标位置不在listview项目上(rect 0, 0, lv.width - scroll.width, lv.height - scroll.height),则防止拖动。 因此,当PreviewMouseLeftButtonDown经过时,我有一个“allowdrag”标志,如果鼠标指针在必要的矩形上方,则变为True。

VB.NET

Private allowdrag As Boolean

Private Sub lv_PreviewMouseLeftButtonDown(sender As Object, e As MouseButtonEventArgs) Handles lvAttributesDefault.PreviewMouseLeftButtonDown
    Dim listView As ListView = TryCast(sender, ListView)
    allowdrag = e.GetPosition(sender).X < listView.ActualWidth - SystemParameters.VerticalScrollBarWidth And e.GetPosition(sender).Y < listView.ActualHeight - SystemParameters.HorizontalScrollBarHeight
End Sub

Private Sub lv_MouseMove(sender As Object, e As MouseEventArgs) Handles lvAttributesDefault.MouseMove
    Dim listView As ListView = TryCast(sender, ListView)

    If e.LeftButton = MouseButtonState.Pressed And listView.SelectedItem IsNot Nothing And allowdrag Then
        Dim obj As clsAttribute = CType(listView.SelectedItem, clsAttribute)
        Dim dragData As New DataObject("clsAttribute", obj)

        DragDrop.DoDragDrop(listView, dragData, DragDropEffects.Copy)
    End If
End Sub

C#(Telerik 代码转换器)

private bool allowdrag;
private void lv_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    ListView listView = sender as ListView;
    allowdrag = e.GetPosition(sender).X < listView.ActualWidth - SystemParameters.VerticalScrollBarWidth & e.GetPosition(sender).Y < listView.ActualHeight - SystemParameters.HorizontalScrollBarHeight;
}

private void lv_MouseMove(object sender, MouseEventArgs e)
{
    ListView listView = sender as ListView;

    if (e.LeftButton == MouseButtonState.Pressed & listView.SelectedItem != null & allowdrag) {
        clsAttribute obj = (clsAttribute)listView.SelectedItem;
        DataObject dragData = new DataObject("clsAttribute", obj);

        DragDrop.DoDragDrop(listView, dragData, DragDropEffects.Copy);
    }
}

PS. clsAttribute 是我自定义的类。ListView 绑定了 ObservableCollection(Of clsAttribute)。


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