2013-04-12 12 views
6

Ich möchte einem Benutzer gestatten, Elemente in einem Flex-Strukturordner neu anzuordnen, diese Elemente jedoch nicht außerhalb des Ordners zu verschieben. Ich kann verhindern, dass der äußere Tropfen erfolgreich ist, aber ich möchte dem Benutzer Feedback geben (vor dem Tropfen), dass der Tropfen nicht erfolgreich sein wird. Ich habe viele Beispiele bezüglich der Drop-Aktion gefunden, aber nichts, das dem Benutzer die richtige Rückmeldung zeigt.Flex-Baum-Rückmeldung verhindern

Entsprechend der Baumdokumentation sollte ich in der Lage sein, DragManager.showFeedback(DragManager.NONE) während des dragOver Ereignisses aufzurufen, aber das funktioniert nicht. Ein kurzes Beispielprojekt ist unten enthalten. Gibt es eine Möglichkeit, dem Benutzer während eines Ziehereignisses anzuzeigen, dass der Abbruch nicht erfolgreich ist?

Vielen Dank im Voraus für jede Lösung!

<?xml version="1.0" encoding="utf-8"?> 
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
         xmlns:s="library://ns.adobe.com/flex/spark" 
         xmlns:mx="library://ns.adobe.com/flex/mx" 
         width="354" 
         height="480"> 
    <fx:Script> 
     <![CDATA[ 
      import mx.collections.ArrayCollection; 
      import mx.core.IUIComponent; 
      import mx.core.mx_internal; 
      import mx.events.DragEvent; 
      import mx.events.FlexEvent; 
      import mx.managers.DragManager; 

      protected function tree_dragEnterHandler(event:DragEvent):void { 
       // only items can be dragged - not folders 
       if ([email protected] == "item") { 
        DragManager.acceptDragDrop(IUIComponent(event.currentTarget)); 
       } else { 
        event.preventDefault(); 
        DragManager.showFeedback(DragManager.NONE); 
       } 
      } 

      protected function tree_dragOverHandler(event:DragEvent):void { 
       var dropData:Object = tree.mx_internal::_dropData; 
       var dragItem:XML = event.dragSource.dataForFormat("treeItems")[0]; 
       if (!dropData || !dropData.parent || !dragItem.parent() || dragItem.parent() != dropData.parent) { 
        trace("preventing drop"); 
        DragManager.showFeedback(DragManager.NONE); 
        return; 
       } 
       trace("allowing drop"); 
       DragManager.showFeedback(DragManager.MOVE); 
      } 

      protected function tree_dragDropHandler(event:DragEvent):void { 
      } 
     ]]> 
    </fx:Script> 
    <fx:Declarations> 
     <fx:XML id="treeData"> 
      <folder id="root" 
        label="root" 
        type="root"> 
       <folder id="folder1" 
         label="Folder 1" 
         type="folder"> 
        <folder id="folder2" 
          label="Folder 2" 
          type="folder"> 
         <item id="item1" 
           label="Item 1" 
           type="item"/> 
         <item id="item2" 
           label="Item 2" 
           type="item"/> 
         <item id="item3" 
           label="Item 3" 
           type="item"/> 
         <item id="item4" 
           label="Item 4" 
           type="item"/> 
         <item id="item5" 
           label="Item 5" 
           type="item"/> 
        </folder> 
       </folder> 
       <folder id="folder3" 
         label="Folder 3" 
         type="folder"/> 
       <folder id="folder4" 
         label="Folder 4" 
         type="folder"/> 
       <folder id="folder5" 
         label="Folder 5" 
         type="folder"/> 
      </folder> 
     </fx:XML> 
    </fx:Declarations> 
    <mx:Tree id="tree" 
      left="29" 
      right="28" 
      top="28" 
      bottom="27" 
      dragEnabled="true" 
      dropEnabled="true" 
      dragMoveEnabled="true" 
      dataProvider="{treeData}" 
      labelField="@label" 
      dragEnter="tree_dragEnterHandler(event)" 
      dragOver="tree_dragOverHandler(event)" 
      dragDrop="tree_dragDropHandler(event)" 
      showRoot="false"> 
    </mx:Tree> 
</s:WindowedApplication> 
+0

Versuchen Sie, alle Ihre Logik in dragEnterHandler setzen - Dokumentation besagt, dass DragEvent.DRAG_ENTER (nicht DragEvent.DRAG_OVER) –

+0

dragEnterHandler() nur aufgerufen wird, von der Verschleppung zu Beginn einmal verwendet werden soll. Ich möchte die Rückmeldung während des Ziehens basierend auf dem Element unter dem Cursor ändern können. –

+0

Dies passiert, weil Sie die Drag-Feedback-Funktion sofort auf "NONE" setzen, nachdem das eingebaute Drag & Drop-Verhalten des Trees es auf "MOVE" zurücksetzt. [Diese Seite] (http://help.adobe.com/de_DE/flex/using/WS2db454920e96a9e51e63e3d11c0bf69084-7cfe.html) zeigt zwei Beispiele für Drag & Drop, einen für Nicht-Listen-Steuerelemente und einen für Listen-basierte Steuerelemente (wie z der Baum). In dem auf Listen basierenden Beispiel haben Sie drei Möglichkeiten: Verwenden Sie integriertes Verhalten, rollen Sie Ihr eigenes oder verwenden Sie eine Kombination aus beidem. Wenn Sie das Drag-feedback auf "NONE" setzen, wird es durch das Standardverhalten überschrieben. –

Antwort

2

Es ist frustrierend, dass die Standard-Drag-and-Drop-Funktionalität fast dies alles Notwendige zu tun liefert, aber nicht ganz. Es scheint, dass die Antwort von IlyaZ funktionieren sollte, aber das könnte ein Fehler in der mx: Tree-Kontrolle von Flex sein.

Ich endete damit, indem ich meine eigene Drag-and-Drop-Implementierung, wie SunilD angedeutet, durchgeführt habe. Der Code ist unten für jeden, der in Zukunft auf das gleiche Problem stoßen könnte, enthalten.

Hinweis, dass es noch ein kleines visuelles Feedback Problem, wenn der Benutzer über die Grenze zwischen maxDropIndex und maxDropIndex+1 schleppt: Am unteren Teil der Grenze des Dropindikator verschiebt, um anzuzeigen, dass es möglich ist, ein Element in dem Ordner löschen Niveau. Ich bin immer noch auf der Suche nach einer guten Lösung (kann mich jemand auf die Baumquelle hinweisen?).

<?xml version="1.0" encoding="utf-8"?> 
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
         xmlns:s="library://ns.adobe.com/flex/spark" 
         xmlns:mx="library://ns.adobe.com/flex/mx" 
         width="354" 
         height="480"> 
    <fx:Script> 
     <![CDATA[ 
      import mx.collections.ArrayCollection; 
      import mx.core.DragSource; 
      import mx.core.IUIComponent; 
      import mx.core.mx_internal; 
      import mx.events.DragEvent; 
      import mx.events.FlexEvent; 
      import mx.managers.DragManager; 

      protected var dragging:Boolean = false; 
      protected var minDropIndex:int = 0; 
      protected var maxDropIndex:int = 0; 

      protected function tree_dragEnterHandler(event:DragEvent):void { 
       // only items can be dropped 
       if (event.dragSource.hasFormat("tree_item_node")) { 
        DragManager.acceptDragDrop(IUIComponent(event.currentTarget)); 
        trace("accepting DragDrop"); 
       } else { 
        event.preventDefault(); 
        DragManager.showFeedback(DragManager.NONE); 
        trace("rejecting DragDrop"); 
       } 
      } 

      protected function tree_dragOverHandler(event:DragEvent):void { 
       var index:int = tree.calculateDropIndex(event); 
       if (index < minDropIndex || index > maxDropIndex) { 
        trace("preventing drop"); 
        DragManager.showFeedback(DragManager.NONE); 
        this.tree.hideDropFeedback(event); 
        return; 
       } 
       trace("allowing drop"); 
       DragManager.showFeedback(DragManager.MOVE); 
       this.tree.showDropFeedback(event); 
      } 

      protected function tree_dragDropHandler(event:DragEvent):void { 
       trace("dragDropHandler"); 
      } 

      protected function tree_mouseMoveHandler(event:MouseEvent):void { 
       // see if we should start a drag operation 
       if (event.buttonDown && !dragging && tree.selectedItem && [email protected] == "item") { 
        // TODO: calculate the min and max drag indices from currently-selected index 
        minDropIndex = 2; 
        maxDropIndex = 7; 

        // start the drag 
        dragging = true; 
        var dragSource:DragSource = new DragSource(); 
        dragSource.addData(tree.selectedItem, "tree_item_node"); 
        DragManager.doDrag(IUIComponent(event.currentTarget), dragSource, event); 
       } 
      } 

      protected function tree_dragCompleteHandler(event:DragEvent):void { 
       trace("dragComplete: no longer dragging"); 
       this.tree.hideDropFeedback(event); 
       dragging = false; 
      } 
     ]]> 
    </fx:Script> 
    <fx:Declarations> 
     <fx:XML id="treeData"> 
      <folder id="root" 
        label="root" 
        type="root"> 
       <folder id="folder1" 
         label="Folder 1" 
         type="folder"> 
        <folder id="folder2" 
          label="Folder 2" 
          type="folder"> 
         <item id="item1" 
           label="Item 1" 
           type="item"/> 
         <item id="item2" 
           label="Item 2" 
           type="item"/> 
         <item id="item3" 
           label="Item 3" 
           type="item"/> 
         <item id="item4" 
           label="Item 4" 
           type="item"/> 
         <item id="item5" 
           label="Item 5" 
           type="item"/> 
        </folder> 
       </folder> 
       <folder id="folder3" 
         label="Folder 3" 
         type="folder"/> 
       <folder id="folder4" 
         label="Folder 4" 
         type="folder"/> 
       <folder id="folder5" 
         label="Folder 5" 
         type="folder"/> 
      </folder> 
     </fx:XML> 
    </fx:Declarations> 
    <mx:Tree id="tree" 
      left="29" 
      right="28" 
      top="28" 
      bottom="27" 
      dragEnabled="false" 
      dropEnabled="false" 
      dataProvider="{treeData}" 
      labelField="@label" 
      dragEnter="tree_dragEnterHandler(event)" 
      dragOver="tree_dragOverHandler(event)" 
      dragDrop="tree_dragDropHandler(event)" 
      dragComplete="tree_dragCompleteHandler(event)" 
      mouseMove="tree_mouseMoveHandler(event)" 
      showRoot="false"> 
    </mx:Tree> 
</s:WindowedApplication>