2009-02-18 41 views
7

Bir süredir Bea'nun çözümü here ile çalışıyorum ve çok yararlı buluyorum. Sorun şu andaki öğeleri sürüklediğimde veya başka bir ListView denetimini düşürdüğümde ve sürükle (kaydırma sırasında bir öğe (indeks 30'dan dizin 1'e geçerken) yukarı/aşağı kaydırmak istediğimde, bu gerçekleşmiyor. ListView'deki görsel öğelerin üstüne sürüklenmeli, el ile yukarı kaydırmalı, sonra tekrar sürüklemeliyim, sonunda istediğim konuma son vermeliyim. Bu çok kullanıcı dostu değil.WPF ListView Databound Sürükle/Bırak Otomatik Kaydırma

Şimdi hangi öğenin sürüklendiğini test etmek istediğimi (DragDropHelper.DropTarget_PreviewDragOver) işlevi buldum ve bunu alıyorum.

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) 

Şimdi oradan bir Listviewıtem 'ın bu görsel isabet

Dim lvi As ListViewItem = TryCast(GetDependencyObjectFromVisualTree(TryCast(result.VisualHit, DependencyObject), GetType(ListViewItem)), ListViewItem) 

ait DependencyProperty alabilirsiniz. Şimdi DropTarget_PreviewDragOver fonksiyonunda Bea'nın örneğindeki tip Picture olan "DraggedItem" var, ancak ListView'e bağlı olan ObservableCollection'a bağlı olarak değişebilir. Şimdi, farenin denetimde olduğu yere bağlı olarak ListView'ı yukarı veya aşağı sürüklemek istiyorum. Birlikte teşebbüs ettik aşağıda un mamul olmayan çalışma kod

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 

birisi öğeleri üzerinde sürüklerken kaydırmak için bu ItemsControl veya ListView almak için doğru yönde işaret edebilir ??

Teşekkürler!

+0

Merhaba, Bir çözüm buldunuz mu? Alkışlar –

+0

Üzgünüm, hala buna bakmak için zamanım olmadı. Gönderinden beri bir şeye rastladın mı? – ScottN

cevap

2

Hala bu aynı sorunla uğraşıyorum hala. Bea's Drag ve Drop biraz değiştirilmiş sürümü kullanıyorum C# yerine VB içinde here bulundu. ScrollIntoView'u yukarıda açıklandığı gibi kullandığımda aşağıya inip çıkabilirdim. Bu yüzden etrafında haberci ve benim DropTarget_PreviewDragOver olarak bu geldi:

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 

ve büyük ve hepsi 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 

alınan bu fayda fonksiyonu dahil etmek zorunda kaldı.Sonra adorner hareket ile yukarıda belirtilen theuberk ve daha sonra başkası için bu kadar kolay hale ruhu içinde, ben DragDropAdorner sınıfına bir değişkeni eklendi neyi azalıyor:

Private m_mouseDelta As Point 

Katma bu DragSource_PreviewMouseLeftButtonDown son satırına:

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 
+0

Sonunda bunu uygulamaya koyup çok hızlı bir şekilde test ettim. Harika görünüyor! İyi çalıştı! Teşekkürler! – ScottN

+0

Bir sorun buldum, iki denetim arasındaki öğeleri sürüklemeye alternatif olarak liste kutusunda çift tıklamayı kullanıyordum. Yukarıdaki gibi bir metodu kullanarak, bir çift tıklama arasında tek bir tıklamayı tespit etmekte sorun yaşanıyordu ve kaynak listeden çıkardığım öğeyi tekrar ekledim. Yani fare aşağı fonksiyonunda "Eğer e.Clicks = 1 Sonra Sürükle Else Set DraggedData = Hiçbir şey" ekledim, düzeltmek gerekir. – ScottN

2

Ne yaptım ListBox.ScrollIntoView yönteminden yararlandı. Temel olarak, bırakma hedefinizi güncellediğinizde, bunun üzerine bu yöntemi çağırabilir ve tüm işi yapacaksınız. Bilmeniz gereken tek şey, bırakılan hedef öğenin dizinidir. Bu hem dikey hem yatay kaydırma işlemlerini gerçekleştirir. Bu yöntemi kullandığınızda

this.listView.ScrollIntoView(this.listView.Items[index]);

, senin adorner kaydırma ListBox ile hareket olabilir. Bunu düzeltmek için, adorner ebeveyni ve adorner katmanı ebeveyni görsel ağacın üstündeki pencerenin içeriğine ayarladım (örn. topWindow.Content).

+1

Bunu deneyeceğim, 3 ay sonra yayınladığın için teşekkürler :) Bunun hakkında unutulduğunu düşündüm .. – ScottN

+0

teşekkürler! Benzer yaptım lstMessages.ScrollIntoView (lstMessages.Items [lstMessages.Items.Count-1]); –

0

kaydırmak için başka olasılık ScrollBar-Komutları kullanmaktır:

 Me.m_mouseDelta = e.GetPosition(m_sourceItemContainer) 

Ve

içine ShowDraggedAdorner döndü. Bunu VisualTree'ye tırmanmadan yapabilirsiniz. Kenarlıksız bir stiller ListBox varsa GetScrollViewer() - Yöntem artık çalışmayacak.

Ben ScrollBar.LineXXXCommand için CommandTarget olarak ItemContainerGenerator ilk Eleman kullanın:

Point p = e.GetPosition(itemsControl); 
    IInputElement commandTarget = itemsControl.ItemContainerGenerator.ContainerFromIndex(0) as IInputElement; 

    if (commandTarget != null) 
    { 
    if (p.Y < OFFSET_TO_SCROLL) 
     ScrollBar.LineUpCommand.Execute(null, commandTarget); 
    else if (p.Y > itemsControl.ActualHeight - OFFSET_TO_SCROLL) 
     ScrollBar.LineDownCommand.Execute(null, commandTarget); 

    if (p.X < OFFSET_TO_SCROLL) 
     ScrollBar.LineLeftCommand.Execute(null, commandTarget); 
    else if (p.X > itemsControl.ActualWidth - OFFSET_TO_SCROLL) 
     ScrollBar.LineRightCommand.Execute(null, commandTarget); 
    } 

LineXXXCommands çağrılması bir kaydırma çubuğu Ok-Düğmeleri tıklayarak benzerlik gösterir: ScrollViewer scrolles belli kestirmeniz tarafından hangi ScrollBar'ın 'SmallAmount' Özelliğini ayarlayarak yapılandırabilirsiniz.

İlgili konular