WPF ListView数据绑定拖放自动滚动

Sco*_*ttN 7 data-binding collections wpf listview drag-and-drop

我已经在这里与Bea的解决方案合作了一段时间,并发现它非常有用.现在我遇到的问题是,当我将项目拖放到另一个ListView控件中时,我想在拖动期间向上/向下滚动(将项目从索引30移动到索引1),它不会发生.我必须拖动到ListView中的可视项目的顶部,手动向上滚动,然后再次拖动,最终在我想要的位置结束.这不是非常用户友好.

现在我找到了我想要测试哪个项目被拖过的函数(DragDropHelper.DropTarget_PreviewDragOver),我就是这样.

Dim pt As Point = e.GetPosition(DirectCast(Me.targetItemsControl, UIElement))

' Perform the hit test against a given portion of the visual object tree.
Dim result As HitTestResult = VisualTreeHelper.HitTest(Me.targetItemsControl, pt)
Run Code Online (Sandbox Code Playgroud)

现在从那里我可以得到这个视觉命中的DependencyProperty

Dim lvi As ListViewItem = TryCast(GetDependencyObjectFromVisualTree(TryCast(result.VisualHit, DependencyObject), GetType(ListViewItem)), ListViewItem)
Run Code Online (Sandbox Code Playgroud)

哪个是ListViewItem.现在在函数DropTarget_PreviewDragOver中我有"DraggedItem",它在Bea的示例中是Picture类型,但是这可以根据你绑定到ListView的ObservableCollection而改变.现在,我想根据鼠标在控件上的位置向上或向下拖动ListView.我尝试使用下面未完成的非工作代码

If lvi IsNot Nothing Then
    If pt.Y <= 25 Then
        Dim lv As ListView = TryCast(targetItemsControl, ListView)
        If lv IsNot Nothing Then
            Dim index As Integer = lv.Items.IndexOf(lvi)
            If index > 1 Then
                lv.ScrollIntoView(lv.Items(index - 1))
            End If
        End If
    Else
        If pt.Y >= Me.targetItemsControl.ActualHeight - 25 Then
            Debug.Print("Scroll Down")
        End If
    End If
End If
Run Code Online (Sandbox Code Playgroud)

有人能指出我正确的方向,以便在拖动项目时滚动这个ItemsControl或ListView吗?

谢谢!

Sco*_* O. 2

我还在搞乱这个完全相同的问题。我正在使用此处找到的 Bea 拖放功能的稍微修改版本,它是用 VB 而不是 C# 编写的。当我如上所述使用 ScrollIntoView 时,我可以向下滚动但不能向上滚动。所以我胡思乱想,想出了这个作为我的 DropTarget_PreviewDragOver:

 Private Sub DropTarget_PreviewDragOver(ByVal sender As Object, ByVal e As DragEventArgs)
        Dim draggedItem As Object = e.Data.GetData(Me.m_format.Name)
        Me.DecideDropTarget(e)
        If (Not draggedItem Is Nothing) Then
            If (TypeOf m_targetItemsControl Is ListBox) Then
                Dim lb As ListBox = CType(m_targetItemsControl, ListBox)
                Dim temp As Integer = m_insertionIndex
                Dim scroll As ScrollViewer = Utilities.GetScrollViewer(lb)
                If scroll.VerticalOffset = temp Then
                    temp -= 1
                End If
                If temp >= 0 And temp <= (lb.Items.Count - 1) Then
                    lb.ScrollIntoView(lb.Items(temp))
                End If
            End If
            Me.ShowDraggedAdorner(e.GetPosition(Me.m_topWindow))
            Me.UpdateInsertionAdornerPosition()
        End If
        e.Handled = True
    End Sub
Run Code Online (Sandbox Code Playgroud)

我必须包括这个实用函数,取自这里

    Public Shared Function GetScrollViewer(ByVal listBox As ListBox)
    Dim scroll_border As Decorator = CType(VisualTreeHelper.GetChild(listBox, 0), Decorator)
    If (TypeOf scroll_border Is Decorator) Then
        Dim scroll As ScrollViewer = CType(scroll_border.Child, ScrollViewer)
        If (TypeOf scroll Is ScrollViewer) Then
            Return scroll
        Else
            Return Nothing
        End If
    Else
        Return Nothing
    End If


End Function
Run Code Online (Sandbox Code Playgroud)

这太棒了。然后用装饰器移动来执行 theuberk 上面提到的内容,并且本着让其他人以后更容易做到这一点的精神,我向 DragDropAdorner 类添加了一个变量:

    Private m_mouseDelta As Point
Run Code Online (Sandbox Code Playgroud)

将其添加到 DragSource_PreviewMouseLeftButtonDown 的最后一行:

        Me.m_mouseDelta = e.GetPosition(m_sourceItemContainer)
Run Code Online (Sandbox Code Playgroud)

并将 ShowDraggedAdorner 变成:

    Private Sub ShowDraggedAdorner(ByVal currentPosition As Point)
    If (Me.m_draggedAdorner Is Nothing) Then
        Dim adornerLayer As AdornerLayer = adornerLayer.GetAdornerLayer(Me.m_topWindow.Content)
        Me.m_draggedAdorner = New DraggedAdorner(Me.m_draggedData, DragDropBehavior.GetDragTemplate(Me.m_sourceItemsControl), m_topWindow.Content, adornerLayer)
    End If
    Me.m_draggedAdorner.SetPosition((currentPosition.X - m_mouseDelta.X), (currentPosition.Y - m_mouseDelta.Y))
    End Sub
Run Code Online (Sandbox Code Playgroud)