2009-02-18 27 views
7

मैं थोड़ी देर के लिए बीए के समाधान here के साथ काम कर रहा हूं और इसे बहुत उपयोगी ढूंढ रहा हूं। समस्या यह है कि जब मैं ड्रैग-एन-ड्रॉप आइटम को किसी अन्य सूची दृश्य नियंत्रण में खींचता हूं और मैं ड्रैग के दौरान "नीचे" स्क्रॉल करना चाहता हूं (इंडेक्स 30 से इंडेक्स 1 तक किसी आइटम को ले जाना), यह नहीं हो रहा है। मुझे सूची दृश्य में दृश्य वस्तुओं के शीर्ष पर खींचना होगा, मैन्युअल रूप से स्क्रॉल करें, फिर फिर से खींचें, आखिरकार जिस स्थिति में मैं चाहता हूं उसे समाप्त कर दूं। यह बहुत उपयोगकर्ता के अनुकूल नहीं है।WPF 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) 

अब वहाँ से मैं इस दृश्य हिट

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

जो एक ListViewItem की है की DependencyProperty मिल सकती है। अब फंक्शन में DropTarget_PreviewDragOver मेरे पास "DraggedItem" है जो बीए के उदाहरण में चित्र प्रकार का है, लेकिन यह ListView से जुड़े पर्यवेक्षण चयन के आधार पर बदल सकता है। अब, माउस नियंत्रण पर है, इस पर निर्भर करता है कि मैं 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 

कोई सही दिशा जब से अधिक आइटम खींचकर स्क्रॉल करने के लिए इस ItemsControl या ListView प्राप्त करने के लिए मुझे बात कर सकते हैं ??

धन्यवाद!

+0

हाय, क्या आपको कोई समाधान मिला? चीयर्स –

+0

क्षमा करें, मेरे पास अभी भी इसे देखने के लिए समय नहीं है। क्या आपने पोस्ट करने के बाद से कुछ पार किया है? – ScottN

उत्तर

2

मैं अभी भी इस सटीक मुद्दे के साथ गड़बड़ कर रहा हूं। मैं बीए ड्रैग एंड ड्रॉप के थोड़ा संशोधित संस्करण का उपयोग कर रहा हूं here, जो सी # के बजाय वीबी में है। जब मैंने उपरोक्त वर्णित स्क्रॉलइंटव्यू का उपयोग किया, तो मैं नीचे स्क्रॉल कर सकता था लेकिन ऊपर नहीं। इसलिए मैं चारों ओर गड़बड़ और मेरे 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

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 

जो महान और सभी है लिया शामिल करने के लिए किया था।तब निकलता जा रहा क्या adorner चलती से ऊपर बताए 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 
+0

मुझे अंततः इसे लागू करने और इसे वास्तव में त्वरित परीक्षण करने के लिए मिला। अच्छा लग रहा है! ठीक काम किया! धन्यवाद! – ScottN

+0

मुझे एक समस्या मिली हालांकि, मैं दो नियंत्रणों के बीच वस्तुओं को खींचने के विकल्प के रूप में सूची बॉक्स पर डबल क्लिक का उपयोग कर रहा था। उपर्युक्त विधि का उपयोग करके इसे डबल क्लिक के बीच एक क्लिक का पता लगाने में समस्याएं आ रही थीं और स्रोत सूची में आइटम को वापस जोड़ा गया था जिसे मैंने अभी हटा दिया था। तो माउस डाउन फंक्शन में मैंने जोड़ा "अगर ई.क्लिक्स = 1 फिर ड्रैगडेटा = कुछ भी नहीं खींचें", तो इसे ठीक करना चाहिए। – ScottN

2

मैंने जो किया वह ListBox.ScrollIntoView विधि का लाभ उठाया गया था। असल में, जब आप अपना ड्रॉप लक्ष्य अपडेट करते हैं, तो आप बस इस विधि को कॉल कर सकते हैं और wpf सभी काम करेगा। आपको केवल ड्रॉप लक्ष्य आइटम की अनुक्रमणिका पता होना चाहिए। यह लंबवत और क्षैतिज स्क्रॉलिंग दोनों को संभालता है।

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

आप इस विधि का उपयोग करते हैं, अपने adorner स्क्रॉल ListBox के साथ ले जाने के कर सकते हैं। इसे ठीक करने के लिए, मैंने दृश्य एड्रेस (यानी topWindow.Content) के शीर्ष पर विंडो की सामग्री पर अपने एडॉर्नर पैरेंट और एडॉर्नर लेयर पेरेंट को बस सेट किया है।

+1

मैं इसे आज़मा दूंगा, 3 महीने बाद पोस्ट करने के लिए धन्यवाद :) मैंने सोचा था कि यह भूल गया था .. – ScottN

+0

धन्यवाद! मैंने इसे lstMessages.ScrollIntoView (lstMessages.Items [lstMessages.Items.Count-1]) किया; –

0

स्क्रॉल करने के लिए एक और संभावना स्क्रॉलपट्टी-कमांड का प्रयोग है। आप VisualTree पर चढ़ने के बिना ऐसा कर सकते हैं। यदि आपके पास कोई सीमा वाली स्टाइल सूची बॉक्स है, तो GetScrollViewer() - विधि अब और काम नहीं करेगी।

मैं ScrollBar.LineXXXCommand के लिए CommandTarget रूप ItemContainerGenerator के पहले तत्व का उपयोग करें:

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 कॉलिंग एक स्क्रॉलबार के तीर-बटन पर क्लिक करने के लिए समान है: एक निश्चित राशि के द्वारा ScrollViewer scrolles जो आप ScrollBar की 'SmallAmount' संपत्ति सेट करके कॉन्फ़िगर कर सकते हैं।

संबंधित मुद्दे