WPF ListView Databound Drag/Drop Auto Scroll

后端 未结 3 715
轻奢々
轻奢々 2021-02-06 09:03

I\'ve been working with Bea\'s solution here for a while and finding it very helpful. Problem now I\'m having is when I drag-n-drop items within or to another ListView control

3条回答
  •  时光取名叫无心
    2021-02-06 10:05

    I'm still messing around with this exact same issue too. I'm using a slightly modified version of Bea's Drag and Drop found here, which is in VB instead of C#. When I used ScrollIntoView as described above, I could scroll down but not up. So I messed around and came up with this as my 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
    

    and I had to include this utility function, taken from here

        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
    

    which is great and all. Then running out what theuberk mentioned above with the adorner moving, and in the spirit of making this easy for someone else later, I added a variable to the DragDropAdorner class:

        Private m_mouseDelta As Point
    

    Added this to the last line of DragSource_PreviewMouseLeftButtonDown:

            Me.m_mouseDelta = e.GetPosition(m_sourceItemContainer)
    

    And turned ShowDraggedAdorner into:

        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
    

提交回复
热议问题