Flex 3入门教程: 使用 Tree 控件

Tree控件是一个枝和叶节点分层次的机构。树中没每一个条目叫做节点,节点既可以作为枝也可以作为叶。枝节点可以包含叶或枝节点,或者为空。一个叶节点就是一个树的末梢。本快速指南包含一些开发者在使用Treecontrols经常会遇到的一些挑战。
 

使用XMLLISTCOLLECTION 和ARRAYCOLLECTION对象的对比。


你也许想知道,在运行时从远程或本地得来的数据被动态修改的时候,应该使用XMLListCollection对象还是ArrayCollection对象作为Tree空间的数据提供者。


如果你使用的数据源提供成形的XML,并且,你想在Tree控件中操作 XML数据。你应该使用XMLListCollection对象作为数据提供者。当使用MXML标记时,如果数据源是XMLList对象,你应该把它绑定到XMLLsitCollection对象的source属性上,然后把 XMLListCollection对象绑定到Tree控件的dataProvider属性上。

当你想要动态改变对象值时,不要使用XMLList或XML对象直接绑定到Tree控件的dataProvider属性上。当数据源是RPC(远程过程调用)服务的lastResult属性,并且你想使用XML数据,确保RPC组件的resultFormat属性被设置成e4x,当你使用e4x结果格式,最总结果就是XMLList,可以绑定在XMLListCollection对象上。

这里有一个例子。为例数据被动态改变,使用ArrayCollection对象作为Tree控件的数据提供器。当使用MXML标记时,如果你期望动态的改变Arrayl,你不应该把Array对象直接绑定到Tree控件的dataProvider属性上。作为代替,你应该绑定Array到一个ArrayCollection对象的source属性上,然后再把ArrayCollection对象绑定到Tree控件的dataProvider属性上。


当数据源是RPC(远程过程调用)服务的lastResult对象,并且RPC组件的resultFormat属性被成object,你应该使用ArrayUtil.toArray()方法来确保对象是一个Array。然后绑定到ArrayCollection对象上,就像下边的例子所示:

 


  1. <mx:ArrayCollection
  2.     id="employeeAC"
  3.     source= "{ArrayUtil.toArray(employeeSrv.lastResult.employees.employee)}"/>

在运行时增加和删除叶子节点


你可以在运行时为Tree控件增加或删除叶子节点。下边的例子包含的代码来实现这种改变。这个程序使用预定义的枝和叶来初始化,表现公司部门和员工。你可以向任意枝节点增加叶节点在运行时。你也可以删除预定义的叶节点和你在运行时增加的节点。


在这个例子中的XML包含两种不同的元素名字,department和employee。Tree控件的label函数,决定根据元素的类型应该显示那些文本。它使用了E4X语法来返回department的title,或者employee的name。然后,这些语法在addEmployee()和removeEmployee()中会用到。


为了增加员工到业务部门,addEmployee()方法使用E4X语法,通过title属性的值获得业务部门的节点,并把它保存到XMLList类型的变量dept中。然后,通过调用dept.appendChild()方法向操作节点添加子结点。remove方法保存当前被选择的元素到变量node中,node的类型是XML。调用node.localName()方法确定被选择的元素是否是employee节点。如果是employee节点,删除它。


例子



 

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="src/index.html">
  3.    
  4.     <mx:Script>
  5.         <![CDATA[            import mx.collections.XMLListCollection;
  6.            
  7.             [Bindable]
  8.             private var company:XML = 
  9.               <list>
  10.                 <department title="Finance" code="200">
  11.                     <employee name="John H"/> 
  12.                     <employee name="Sam K"/>
  13.                 </department>
  14.                 <department title="Operations" code="400"
  15.                     <employee name="Bill C"/>
  16.                     <employee name="Jill W"/>
  17.                 </department>                   
  18.                 <department title="Engineering" code="300"
  19.                     <employee name="Erin M"/>
  20.                     <employee name="Ann B"/>
  21.                 </department>                               
  22.               </list>;
  23.            
  24.             [Bindable] 
  25.             private var companyData:XMLListCollection = new XMLListCollection(company.department);
  26.            
  27.             private function treeLabel(item:Object):String
  28.             { 
  29.                 var node:XML = XML(item);
  30.                 if( node.localName() == "department" ) 
  31.                     return node.@title;
  32.                 else
  33.                     return node.@name;
  34.             }
  35.             private function addEmployee():void 
  36.             {
  37.                 var newNode:XML = <employee/>;
  38.                 newNode.@name = empName.text;
  39.                 var dept:XMLList =company.department.(@title == "Operations");
  40.                 if( dept.length() > 0 ) { 
  41.                     dept[0].appendChild(newNode);
  42.                     empName.text = "";
  43.                 }
  44.             } 
  45.             private function removeEmployee():void
  46.             {
  47.                 var node:XML = XML(tree.selectedItem);
  48.                 if( node == null ) return;
  49.                 if( node.localName() != "employee" ) return;
  50.            
  51.                 var children:XMLList = XMLList(node.parent()).children();
  52.                 for(var i:Number=0; i < children.length(); i++) { 
  53.                     if( children[i].@name == node.@name ) {
  54.                         delete children[i];
  55.                     } 
  56.                 }
  57.             }
  58.         ]]>
  59.     </mx:Script>
  60.    
  61.     <mx:Tree id="tree" top="72" left="50" dataProvider="{companyData}"
  62.         labelFunction="treeLabel"
  63.          height="224" width="179"/> 
  64.     <mx:HBox>       
  65.         <mx:Button label="Add Operations Employee" click="addEmployee()"/><mx:TextInput id="empName"/> 
  66.     </mx:HBox>
  67.     <mx:Button label="Remove Selected Employee" click="removeEmployee()"/>   
  68. </mx:Application>

 提示:可以通过右键flash查看官方源文件

在运行时添加一个空的枝节点


可以在运行时向Tree控件添加空的枝节点。下边的例子展示了通过数据提供器(data provider)API和数据描述器(data descriptor )API添加枝节点。通常,添加枝节点的首选途径是通过数据提供器(data provider)API。


addEmptyBranthDP()方法通过数据提供器API向使用XML数据提供器的Tree组件增加一个空节点,这个方法为新节点创建一个XML类型的变量,并且设置这个节点的isBranch属性为true来创建一个枝节点。然后这个方法调用Tree控件的dataProvider.addItemAt()方法来向Tree控件的数据提供器增加新的元素。


addEmptyBranchDP2()方法通过数据提供器API向使用对象数据提供器的Tree组件增加一个空节点,这个方法使用children属性创建一个新的对象,使用children属性能够确保isBranch()方法返回true。然后,这个方法调用Tree控件的dataProvider.addItemAt()方法来向Tree控件的数据提供器增加新的对象。


addEmptyBranchDD()方法通过数据描述器(data descripter)API。这个方法创建一个XML类型的变量,并且设置isBranch属性为true来创建一个枝节点。然后,这个方法调用Tree控件的dataDescriptor.addChildAt()方法来向Tree控件的数据描述器添加一个新的子节点。


例子


  1. <?xml version="1.0" encoding="utf-8"?>
  2. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="src/index.html">    <mx:Script>
  3.         <![CDATA[ 
  4.             [Bindable]
  5.             private var dataX:XML =
  6.                 <item label="Top"
  7.                 <item label="Child One"/>
  8.                 <item label="Child Two" />
  9.             </item>;
  10.        
  11.             [Bindable] 
  12.             private var dataObj:Object =
  13.                 [{label:"Top", children:
  14.                 [ 
  15.                 {label:"Child One"}, {label: "Child Two"}
  16.                 ] 
  17.                 }];
  18.        
  19.             // Adding a branch by going through the Tree control's dataProvider. This is
  20.             // the preferred method.
  21.             // Toggling the isBranch attribute to true causes DefaultDataDescriptor.isBranch()
  22.             // to return true and the Tree treats the node as a branch.
  23.             private function addEmptyBranchDP():void 
  24.             {
  25.                 var newNode:XML = <item label='Middle' isBranch="true"></item>;
  26.                 xmlBound2Tree.dataProvider.addItemAt(newNode, 1);
  27.             } 
  28.        
  29.             // For an object graph, the key point is that the children property needs to be defined,
  30.             // even if it is empty.
  31.             // This causes isBranch() to return true and the Tree treats the new node as a branch.
  32.             private function addEmptyBranchDP2():void
  33.             { 
  34.                 var newObj:Object = {label:"Middle", children:[]};
  35.                 objGraphBound2Tree.dataProvider.addItemAt(newObj, 1);
  36.             } 
  37.        
  38.             // Adding a branch by going through the Tree control's dataDescriptor.
  39.             private function addEmptyBranchDD():void
  40.             {
  41.                 var newNode:XML = <item label='Child 4' isBranch="true"></item>;
  42.                 xmlBound2Tree.dataDescriptor.addChildAt(dataX, newNode, 2, dataX);
  43.             } 
  44.           ]]>
  45.     </mx:Script> 
  46.     <mx:Label text="Tree with XML data"/>
  47.     <mx:Tree id="xmlBound2Tree" dataProvider="{dataX}" labelField="@label" showRoot="true" width="200"/> 
  48.     <mx:Button label="Add Empty Branch through the dataProvider" click="addEmptyBranchDP();"/>
  49.     <mx:Button label="Add Empty Branch through the dataDescriptor" click="addEmptyBranchDD();"/> 
  50.     <mx:Spacer height="10"/>
  51.     <mx:Label text="Tree with object data"/>
  52.     <mx:Tree id="objGraphBound2Tree" dataProvider="{dataObj}" width="200"/> 
  53.     <mx:Button label="Add Empty Branch through the dataProvider" click="addEmptyBranchDP2();"/>   
  54. </mx:Application>

 

结果


打开树到指定的节点

 

默认的,Tree控件在初始化后是收缩的,你也许不确定如何初始化控件时展开数,并且选定指定的节点。下边的例子,展示了如何实现它。在这个程序中,initTree()方法,在Tree控件被创建后调用。这个方法展开Tree控件的根节点,并且设置selectedIndex属性为指定节点的索引号。

  1. <?xml version="1.0"?>
  2. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="src/index.html">    <mx:Script>
  3.         <![CDATA[
  4.             import Flash.events.*;
  5.             import mx.events.*;
  6.             import mx.controls.*;
  7.             private function initTree():void { 
  8.                 XMLTree1.expandItem(MailBox.getItemAt(0), true);
  9.                 XMLTree1.selectedIndex = 2;
  10.             }
  11.         ]]> 
  12.     </mx:Script> 
  13.     <mx:Tree id="XMLTree1" width="150" height="170"
  14.              labelField="@label" creationComplete="initTree();"
  15.         <mx:XMLListCollection id="MailBox">
  16.             <mx:XMLList>
  17.                 <node label="Mail" data="100"
  18.                     <node label="Inbox" data="70"/>
  19.                     <node label="Personal Folder" data="10"
  20.                         <node label="Business" data="2"/>
  21.                         <node label="Demo" data="3"/> 
  22.                         <node label="Saved Mail" data="5" />
  23.                     </node>
  24.                     <node label="Sent" data="15"/> 
  25.                     <node label="Trash" data="5"/>
  26.                  </node>
  27.             </mx:XMLList>
  28.         </mx:XMLListCollection> 
  29. </mx:Tree>
  30. </mx:Application>

结果


读取多节点名XML文档


你可以从具有多个节点名字的XML文档中组装Tree 控件。下边的例子实现了这个功能。Tree控件的数据提供者是一个XMLListCollection,它组装自一个包含folder和Pfolder元素的XMLList。Tree控件的labelField属性被设置为label属性,不管元素叫什么名字,这个属性对XMLList中的所有属性都是公共的。
 

例子

 

  1. <?xml version="1.0"?>
  2. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="src/index.html">
  3.     <mx:Tree id="tree1" dataProvider="{MailBox}" labelField="@label" showRoot="true" width="160"/>
  4.     <mx:XMLListCollection id="MailBox" source="{Folders}"/>
  5.      <mx:XMLList id="Folders">
  6.         <folder label="Mail">
  7.             <folder label="INBOX"/>
  8.             <folder label="Personal Folder">
  9.                 <Pfolder label="Business" />
  10.                 <Pfolder label="Demo" /> 
  11.                 <Pfolder label="Saved Mail" /> 
  12.             </folder>
  13.             <folder label="Sent" />
  14.             <folder label="Trash" />
  15.         </folder>
  16.     </mx:XMLList>    
  17. </mx:Application>
结果


当数据提供器更新时保持Tree控件打开


默认地,当数据提供器更新数据时Tree控件收缩。下边的例子展示了当数据提供器更新时保持Tree控件打开的方法。
在这个应用程序中,当一个用户单击Button控件时changeProvider()方法更新数据提供器。通常,这会导致Tree控件收缩。然而,Tree控件的渲染事件处理器,renderTree()方法,放置收缩的发生。当changerProvider()方法被调用,当前状态是打开的元素被保存到对象open变量中。当数据被刷新时,被命名为refreshData的Boolean类型的变量被置为true。renderTree()方法调用Tree控件的invalidateList()方法来刷新树的行。然后置refreshDate属性为false,并且重置Tree控件的打开元素属性为open对象变量,这个变量在刷新前就包含了状态是打开的元素。


例子

 

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" initialize="initTree()" viewSourceURL="srcview/index.html">
  3.     <mx:Script>
  4.         <![CDATA[
  5.             [Bindable]
  6.             public var open:Object = new Object();
  7.             [Bindable]
  8.             public var refreshData:Boolean = false;
  9.             [Bindable]
  10.             public var switchObj:Object = new Object();
  11.             [Bindable]
  12.             public var firstObj:Object = new Object();
  13.             [Bindable]
  14.             public var firstObj1:Object = new Object();
  15.             [Bindable]
  16.             public var firstObj2:Object = new Object();
  17.             [Bindable]
  18.             public var provider:String = "firstObj";
  19.             private function initTree():void
  20.             {
  21.                 firstObj = new Object();
  22.                 firstObj.label = "Foods";
  23.                 firstObj.children = new Array();
  24.                 firstObj1.label = "Fruits";
  25.                 firstObj1.children = new Array();
  26.                 firstObj2.label = "Oranges";
  27.                 firstObj1.children[0] = firstObj2;
  28.                 firstObj.children[0] = firstObj1;
  29.                 switchObj = firstObj;
  30.             }
  31.             public function changeProvider():void
  32.             {
  33.                 open = SampleTree.openItems;
  34.                 refreshData = true;
  35.                 if (provider == "firstObj")
  36.                 {
  37.                     provider = "switchObj";
  38.                     SampleTree.dataProvider = switchObj;
  39.                 }
  40.                 else
  41.                 {
  42.                     provider = "firstObj";
  43.                     SampleTree.dataProvider = firstObj;
  44.                 }
  45.             }
  46.             public function renderTree():void{
  47.                 if(refreshData){
  48.                     // Refresh all rows on next update.
  49.                     SampleTree.invalidateList();
  50.                     refreshData = false;
  51.                     SampleTree.openItems = open;
  52.                     // Validate and update the properties and layout
  53.                     // of this object and redraw it, if necessary.
  54.                     SampleTree.validateNow();
  55.                 }
  56.             }
  57.         ]]>
  58.     </mx:Script>
  59.     <mx:Tree id="SampleTree" render="renderTree()" width="250" dataProvider="{firstObj}" labelField="label" />
  60.     <mx:Button label="Change Data Provider" click="changeProvider()"/>
  61. </mx:Application>
结果

项和一个树控件拖放
 
拖拽元素到Tree控件,和从Tree控件拖拽出元素创建一个应用程序,实现拖拽元素从Tree控件中,或到Tree控件是令人畏惧的,很明显,因为需要大量的事件处理逻辑。本节提供2个例子,来示范实现这2种功能的技术。从Tree控件中拖拽出元素下边的例子展示如何从Tree控件中拖拽元素到DataGrid控件中。Tree控件的数据提供器是XML对象。通过拖拽事件处理方法前的注释可以使你读懂整个应用程序。

例子

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
  3.     <mx:Script>
  4.         <![CDATA[
  5.             import mx.controls.Alert;
  6.             import mx.controls.Label;
  7.             import mx.controls.List;
  8.             import mx.collections.ArrayCollection;
  9.             import mx.core.DragSource;
  10.             import mx.controls.Tree;
  11.             import mx.controls.DataGrid;
  12.             import mx.controls.listClasses.ListBase;
  13.             import mx.events.DragEvent;
  14.             import mx.containers.Canvas;
  15.             import mx.managers.DragManager;
  16.             import mx.core.UIComponent;
  17.         
  18.             [Bindable]
  19.             private var dataGridProvider:ArrayCollection = new ArrayCollection();
  20.             /**
  21.              * Handles the dragEnter event on the DataGrid control.
  22.              * If the dragInitiator is the Tree control, then only nodes of type "restaurant"
  23.              * are permitted to be dropped.
  24.              * Here you can see that by examining the dragSource you can determine if
  25.              * the control should accept the drop. The DataGrid control would not
  26.              * know how to treat a branch+children from the Tree control, so only leaf (restaurant)
  27.              * nodes are accepted.
  28.              */
  29.             private function onDragEnter( event:DragEvent ) : void
  30.             {            
  31.                 if( event.dragInitiator is Tree ) {
  32.                     var ds:DragSource = event.dragSource;
  33.                     if( !ds.hasFormat("treeItems") ) return;     // no useful data
  34.                     var items:Array = ds.dataForFormat("treeItems") as Array;
  35.                     for(var i:Number=0; i < items.length; i++) {
  36.                         var item:XML = XML(items[i]);
  37.                         if( item.@type != "restaurant" ) return// not what we want
  38.                     }
  39.                 } 
  40.               // If the Tree control passes or the dragInitiator is not a Tree control,
  41.              // accept the drop.
  42.             DragManager.acceptDragDrop(UIComponent(event.currentTarget)); 
  43.             }        
  44.             /**
  45.              * Handles the dragOver event on the DataGrid control.
  46.              * If the dragInitiator is the Tree control, only copy is allowed. Otherwise, a move
  47.              * or link can take place from the List control.
  48.              */
  49.             private function onDragOver( event:DragEvent ) : void
  50.             {
  51.                 if( event.dragInitiator is Tree ) {
  52.                     DragManager.showFeedback(DragManager.COPY);
  53.                 } else {
  54.                     if (event.ctrlKey)
  55.                     DragManager.showFeedback(DragManager.COPY);
  56.                     else if (event.shiftKey)
  57.                         DragManager.showFeedback(DragManager.LINK);
  58.                     else {
  59.                         DragManager.showFeedback(DragManager.MOVE);
  60.                     }
  61.                 }
  62.             }        
  63.             /**
  64.              * Handles the dragExit event on the drop target and just hides the 
  65.              * the drop feedback.
  66.              */
  67.             private function onDragExit( event:DragEvent ) : void
  68.             {
  69.                 var dropTarget:ListBase=ListBase(event.currentTarget);   
  70.             dropTarget.hideDropFeedback(event);
  71.             }
  72.             /**
  73.              * Handles the dragDrop event on the DataGrid when the 
  74.              * drag proxy is released. 
  75.              */
  76.             private function onGridDragDrop( event:DragEvent ) : void
  77.             {
  78.                 var ds:DragSource = event.dragSource;
  79.                 var dropTarget:DataGrid = DataGrid(event.currentTarget);
  80.                 var arr:Array;
  81.                 if( ds.hasFormat("items") ) {
  82.                     arr = ds.dataForFormat("items") as Array;
  83.                 } else if( ds.hasFormat("treeItems") ) {
  84.                     arr = ds.dataForFormat("treeItems") as Array;
  85.                 }
  86.                 for(var i:Number=0; i < arr.length; i++) {
  87.                     var node:XML = XML(arr[i]);
  88.                     var item:Object = new Object();
  89.                     item.label = node.@label;
  90.                     item.type  = node.@type;
  91.                     dataGridProvider.addItem(item);
  92.                 }
  93.                 onDragExit(event); 
  94.             }
  95.             /**
  96.             * Intercepts the dragComplete event on the Tree control
  97.             * and prevents the default behavior from happening. This is necessary
  98.             * if the item being dragged from the Tree control is dropped on a non-Tree
  99.             * object, such as the DataGrid.
  100.             */
  101.             private function onTreeDragComplete(event:DragEvent):void {
  102.                 event.preventDefault();
  103.             }        
  104.             /**
  105.             * Selects all of the items in the List if Ctrl+A is picked when the List control
  106.             * has focus.
  107.             */
  108.             private function selectAllMaybe( event:KeyboardEvent ) : void
  109.             {
  110.                 if( event.ctrlKey && event.keyCode == 65 ) {
  111.                     var l:List = List(event.currentTarget);
  112.                     var allItems:Array = new Array(l.dataProvider.length);
  113.                     for(var i:Number=0; i < allItems.length; i++) {
  114.                         allItems[i] = i;
  115.                     }
  116.                     l.selectedIndices = allItems;
  117.                 }
  118.             }
  119.         ]]>
  120.     </mx:Script>
  121.     <mx:XML id="treeData" xmlns="">
  122.         <root>
  123.             <node label="Massachusetts" type="state" data="MA">
  124.                 <node label="Boston" type="city" >
  125.                     <node label="Smoke House Grill" type="restaurant" />
  126.                     <node label="Equator" type="restaurant" />
  127.                     <node label="Aquataine" type="restaurant" />
  128.                     <node label="Grill 23" type="restaurant" />
  129.                 </node>
  130.                 <node label="Provincetown" type="city" >
  131.                     <node label="Lobster Pot" type="restaurant" />
  132.                     <node label="The Mews" type="restaurant" />
  133.                 </node>
  134.             </node>
  135.             <node label="California" type="state" data="CA">
  136.                 <node label="San Francisco" type="city" >
  137.                     <node label="Frog Lane" type="restaurant" />
  138.                 </node>
  139.             </node>
  140.         </root>
  141.     </mx:XML>
  142.         
  143.     <mx:Label x="34" y="40" text="Drag items from this Tree"/>
  144.     <mx:Label x="34" y="55" text="(items are copied)"/>
  145.     <mx:Tree x="34" y="81" width="181" height="189"
  146.         dataProvider="{treeData.node}"
  147.         labelField="@label"
  148.         dropEnabled="false"
  149.         dragEnabled="true"
  150.         dragComplete="onTreeDragComplete(event)"
  151.         dragMoveEnabled="false"
  152.         />
  153.     <mx:Label x="291" y="55" text="Drop items from Tree here"/>
  154.     <mx:DataGrid x="291" y="81" height="189"
  155.         dragEnabled="true"
  156.         dataProvider="{dataGridProvider}"
  157.         dragEnter="onDragEnter(event)"
  158.         dragOver="onDragOver(event)"
  159.         dragDrop="onGridDragDrop(event)"
  160.         dragExit="onDragExit(event)">
  161.         <mx:columns>
  162.             <mx:DataGridColumn headerText="Label" dataField="label"/>
  163.             <mx:DataGridColumn headerText="Type" dataField="type"/>
  164.         </mx:columns>
  165.     </mx:DataGrid>
  166. </mx:Application>

 

树控件拖放

下面的示例演示如何将项从列表控件拖到树控件。 树数据提供程序是XML对象。

例子

 

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
  3.     <mx:Script>
  4.         <![CDATA[
  5.             import mx.events.DragEvent;
  6.             import mx.managers.DragManager;
  7.             import mx.core.DragSource;
  8.             import mx.core.UIComponent;
  9.             import mx.controls.Tree;
  10.             /**
  11.              * Called as soon as the dragProxy enters the target. You can add logic
  12.              * to determine if the target will accept the drop based on the
  13.              * dragInitiator, the data available in the dragSource.
  14.              * Here the drop is blindly accepted.
  15.              */
  16.             private function onDragEnter( event:DragEvent ) : void
  17.             {
  18.                 DragManager.acceptDragDrop(UIComponent(event.currentTarget));
  19.             }
  20.             /**
  21.              * Called while the dragProxy is over the drop target. You can
  22.              * use this function to determine the type of feedback to show.
  23.              * Since the List is set to allow MOVE (the item is deleted
  24.              * once dropped), different feedback possibilities are given.
  25.              *
  26.              * Also, for this application, the Tree control node the dragProxy is
  27.              * over is selected. As the dragProxy moves, the Tree control's
  28.              * selection changes.
  29.              *
  30.              * For a bit more complication, the drop is being allowed
  31.              * only over nodes whose type is NOT 'state'.
  32.              * The feedback is removed.
  33.              */
  34.             private function onDragOver( event:DragEvent ) : void
  35.             {
  36.                 var dropTarget:Tree = Tree(event.currentTarget);
  37.                 var r:int = dropTarget.calculateDropIndex(event);
  38.                 tree.selectedIndex = r;
  39.                 var node:XML = tree.selectedItem as XML;
  40.                 if( node.@type == "state" ) {
  41.                     DragManager.showFeedback(DragManager.NONE);
  42.                     return;
  43.                 }
  44.                 if (event.ctrlKey)
  45.                     DragManager.showFeedback(DragManager.COPY);
  46.                 else if (event.shiftKey)
  47.                     DragManager.showFeedback(DragManager.LINK);
  48.                 else {
  49.                     DragManager.showFeedback(DragManager.MOVE);
  50.                 }
  51.             }
  52.             /**
  53.              * Called when the dragProxy is released
  54.              * over the drop target. The information in the dragSource
  55.              * is extracted and processed.
  56.              *
  57.              * The target node is determined and 
  58.             * all of the data selected (the List has allowMultipleSection
  59.             * set) is added.
  60.              */
  61.             private function onDragDrop( event:DragEvent ) : void
  62.             {
  63.                 var ds:DragSource = event.dragSource;
  64.                 var dropTarget:Tree = Tree(event.currentTarget);
  65.                 var items:Array = ds.dataForFormat("items") as Array;
  66.                 var r:int = tree.calculateDropIndex(event);
  67.                 tree.selectedIndex = r;
  68.                 var node:XML = tree.selectedItem as XML;
  69.                 var p:*;
  70.                 // if the selected node has children (it is type==city),
  71.                 // then add the items at the beginning
  72.                 if( tree.dataDescriptor.hasChildren(node) ) {
  73.                     p = node;
  74.                     r = 0;
  75.                 } else {
  76.                     p = node.parent();
  77.                 }
  78.                 for(var i:Number=0; i < items.length; i++) {
  79.                     var insert:XML = <node />;
  80.                     insert.@label = items[i];
  81.                     insert.@type  = "restaurant";
  82.                     tree.dataDescriptor.addChildAt(p, insert, r+i);
  83.                 }
  84.             }
  85.             /**
  86.              * Called when the drag operation completes, whether 
  87.              * successfully or not. The tree is cleared of its
  88.              * selection.
  89.              */
  90.             private function onDragComplete( event:DragEvent ) : void
  91.             {
  92.                 tree.selectedIndex = -1;
  93.             }        
  94.         ]]>
  95.     </mx:Script>    
  96.     <mx:XML id="treeData" xmlns="">
  97.         <root>
  98.             <node label="Massachusetts" type="state" data="MA">
  99.                 <node label="Boston" type="city" >
  100.                     <node label="Smoke House Grill" type="restaurant" />
  101.                     <node label="Equator" type="restaurant" />
  102.                     <node label="Aquataine" type="restaurant" />
  103.                     <node label="Grill 23" type="restaurant" />
  104.                 </node>
  105.                 <node label="Provincetown" type="city" >
  106.                     <node label="Lobster Pot" type="restaurant" />
  107.                     <node label="The Mews" type="restaurant" />
  108.                 </node>
  109.             </node>
  110.             <node label="California" type="state" data="CA">
  111.                 <node label="San Francisco" type="city" >
  112.                     <node label="Frog Lane" type="restaurant" />
  113.                 </node>
  114.             </node>
  115.         </root>
  116.     </mx:XML>    
  117.     <mx:Array id="listData">
  118.         <mx:String>Johnny Rocket's</mx:String>
  119.         <mx:String>Jet Pizza</mx:String>
  120.         <mx:String>Steve's Greek</mx:String>
  121.         <mx:String>Sonsie</mx:String>
  122.         <mx:String>The Border Cafe</mx:String>
  123.     </mx:Array>    
  124.     <mx:Panel x="48" y="125" width="447" height="351" layout="absolute" title="Drag onto Tree">    
  125.         <mx:Tree width="186" left="10" top="10" bottom="10" id="tree"
  126.             labelField="@label"
  127.             dataProvider="{treeData.node}"
  128.             dropEnabled="false"
  129.             dragMoveEnabled="false"
  130.             dragEnter="onDragEnter(event)"
  131.             dragOver="onDragOver(event)"
  132.             dragDrop="onDragDrop(event)">
  133.         </mx:Tree>        
  134.         <mx:List width="188" height="206" right="10" bottom="10" id="list"
  135.             allowMultipleSelection="true"
  136.             dataProvider="{listData}"
  137.             dragEnabled="true"
  138.             dragMoveEnabled="true"
  139.             dragComplete="onDragComplete(event)">
  140.         </mx:List>        
  141.         <mx:Text x="229" y="10" text="Drag from the list below to the tree" width="188" height="39"/>
  142.         <mx:Label x="229" y="69" text="restaurants"/>
  143.     </mx:Panel>    
  144. </mx:Application>
 结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值