我还在搞乱这个完全相同的问题。我正在使用 Bea 的拖放功能的稍微修改版本here http://hinshlabs.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=31504,这是用 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
我必须包括这个实用函数,取自here http://www.developingfor.net/wpf/fun-with-the-wpf-scrollviewer.html
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
这太棒了。然后用装饰器移动来执行 theuberk 上面提到的内容,并且本着让其他人以后更容易做到这一点的精神,我向 DragDropAdorner 类添加了一个变量:
Private m_mouseDelta As Point
将其添加到 DragSource_PreviewMouseLeftButtonDown 的最后一行:
Me.m_mouseDelta = e.GetPosition(m_sourceItemContainer)
并将 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