Creating a custom data descriptor

Creating a custom data descriptor

If your hierarchical data does not fit the formats supported by the DefaultDataDescriptor class, for example if your data is in an object that does not use a children field, you can write a custom data descriptor and specify it in your Tree control's dataDescriptor property. The custom data descriptor must implement all methods of the ITreeDataDescriptor interface.

The following example shows how you can create a custom data descriptor, in this case, for use with a Tree control. This data descriptor correctly handles a data provider that consists of nested ArrayCollection objects.

The following code shows the MyCustomTreeDataDescriptor class, which implements only the ITreeDataDescriptor interface, so it supports Tree controls, but not menu-based controls. The custom class supports tree nodes whose children field is either an ArrayCollection or an Object. When getting a node's children, if the children object is an ArrayCollection, it returns the object; otherwise, it wraps the children object in an ArrayCollection before returning it. When adding a node, it uses a different method to add the node, depending on the children field type.

package myComponents
// myComponents/MyCustomTreeDataDescriptor.as
{
import mx.collections.ArrayCollection;
import mx.collections.CursorBookmark;
import mx.collections.ICollectionView;
import mx.collections.IViewCursor;
import mx.events.CollectionEvent;
import mx.events.CollectionEventKind;
import mx.controls.treeClasses.*;

public class MyCustomTreeDataDescriptor implements ITreeDataDescriptor
{

    // The getChildren method requires the node to be an Object
    // with a children field.
    // If the field contains an ArrayCollection, it returns the field
    // Otherwise, it wraps the field in an ArrayCollection.
    public function getChildren(node:Object,
        model:Object=null):ICollectionView
    {
        try
        {
            if (node is Object) {
                if(node.children is ArrayCollection){
                    return node.children;
                }else{
                    return new ArrayCollection(node.children);
                }
            }
        }
        catch (e:Error) {
            trace("[Descriptor] exception checking for getChildren");
        }
        return null;
    }

    // The isBranch method simply returns true if the node is an
    // Object with a children field.
    // It does not support empty branches, but does support null children
    // fields.
    public function isBranch(node:Object, model:Object=null):Boolean {
        try {
            if (node is Object) {
                if (node.children != null)  {
                    return true;
                }
            }
        }
        catch (e:Error) {
            trace("[Descriptor] exception checking for isBranch");
        }
        return false;
    }

    // The hasChildren method Returns true if the
    // node actually has children. 
    public function hasChildren(node:Object, model:Object=null):Boolean {
        if (node == null) 
            return false;
        var children:ICollectionView = getChildren(node, model);
        try {
            if (children.length > 0)
                return true;
        }
        catch (e:Error) {
        }
        return false;
    }
    // The getData method simply returns the node as an Object.
    public function getData(node:Object, model:Object=null):Object {
        try {
            return node;
        }
        catch (e:Error) {
        }
        return null;
    }

    // The addChildAt method does the following:
    // If the parent parameter is null or undefined, inserts
    // the child parameter as the first child of the model parameter.
    // If the parent parameter is an Object and has a children field,
    // adds the child parameter to it at the index parameter location.
    // It does not add a child to a terminal node if it does not have
    // a children field.
    public function addChildAt(parent:Object, child:Object, index:int, 
            model:Object=null):Boolean {
        var event:CollectionEvent = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
        event.kind = CollectionEventKind.ADD;
        event.items = [child];
        event.location = index;
        if (!parent) {
            var iterator:IViewCursor = model.createCursor();
            iterator.seek(CursorBookmark.FIRST, index);
            iterator.insert(child);
        }
        else if (parent is Object) {
            if (parent.children != null) {
                if(parent.children is ArrayCollection) {
                    parent.children.addItemAt(child, index);
                    if (model){
                        model.dispatchEvent(event);
                        model.itemUpdated(parent);
                    }
                    return true;
                }
                else {
                    parent.children.splice(index, 0, child);
                    if (model)
                        model.dispatchEvent(event);
                    return true;
                }
            }
        }
        return false;
    }

    // The removeChildAt method does the following:
    // If the parent parameter is null or undefined,
    // removes the child at the specified index
    // in the model.
    // If the parent parameter is an Object and has a children field,
    // removes the child at the index parameter location in the parent.
    public function removeChildAt(parent:Object, child:Object, index:int, model:Object=null):Boolean
    {
        var event:CollectionEvent = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
        event.kind = CollectionEventKind.REMOVE;
        event.items = [child];
        event.location = index;

        //handle top level where there is no parent
        if (!parent)
        {
            var iterator:IViewCursor = model.createCursor();
            iterator.seek(CursorBookmark.FIRST, index);
            iterator.remove();
            if (model)
                model.dispatchEvent(event);
            return true;
        }
        else if (parent is Object)
        {
            if (parent.children != undefined)
            {
                parent.children.splice(index, 1);
                if (model) 
                    model.dispatchEvent(event);
                return true;
            }
        }
        return false;
    }

}
}

The following example uses the MyCustomTreeDataDescriptor to handle hierarchical nested ArrayCollections and objects. When you click the button it adds a node to the tree by calling the data descriptor's addChildAt() method. Notice that you would not normally use the addChildAt() method directly. Instead, you would use the methods of a Tree or menu-based control, which, in turn, use the data descriptor methods to modify the data provider.

<?xml version="1.0" encoding="iso-8859-1"?>
<!-- dpcontrols/CustDataDescriptor.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*" creationComplete="initCollections()">

    <mx:Script>
        <![CDATA[
            import mx.collections.*;
            import mx.controls.treeClasses.*;
            import myComponents.*;
    
            //Variables used to construct the ArrayCollection data provider
            //First top-level node and its children.
            public var nestArray1:Array = [
                {label:"item1", children: [
                    {label:"item1 child", children:     [
                        {label:"item 1 child child", data:"child data"}
                    ]}
                ]}
            ]; 
            //Second top-level node and its children.
            public var nestArray2:Array = [
                {label:"item2", children: [
                    {label:"item2 child", children: [
                        {label:"item 2 child child", data:"child data"}
                    ]}
                ]}
            ];
            //Second top-level node and its children.
            public var nestArray3:Array = [
                {label:"item3", children: [
                    {label:"item3 child", children: [
                        {label:"item 3 child child", data:"child data"}
                    ]}
                ]}
            ]; 
            //Variable for the tree array.
            public var treeArray:Array
            //Variables for the three Array collections that correspond to the 
            //top-level nodes.
            public var col1:ArrayCollection;
            public var col2:ArrayCollection;
            public var col3:ArrayCollection;
            //Variable for the ArrayCollection used as the Tree data provider.
            [Bindable]
            public var ac:ArrayCollection;
            
            //build the ac ArrayCollection from its parts.
            public function initCollections():void{
                // Wrap each top-level node in an ArrayCollection.
                col1 = new ArrayCollection(nestArray1);
                col2 = new ArrayCollection(nestArray2);
                col3 = new ArrayCollection(nestArray3);
                // Put the three top-level node
                // ArrayCollections in the treeArray.
                treeArray = [
                    {label:"first thing", children: col1},
                    {label:"second thing", children: col2},
                    {label:"third thing", children: col3},
                ]; 
                //Wrap the treeArray in an ArrayCollection.
                ac = new ArrayCollection(treeArray);
            }

            // Adds a child node as the first child of the selected node,
            // if any. The default selectedItem is null, which causes the
            // data descriptor addChild method to add it as the first child
            // of the ac ArrayCollection.
            public function clickAddChildren():void {
                var newChild:Object = new Object();
                newChild.label = "New Child";
                newChild.children = new ArrayCollection();
                tree.dataDescriptor.addChildAt(tree.selectedItem, newChild, 0, ac);
            }

        ]]>
    </mx:Script>

    <mx:Tree width="200" id="tree" dataProvider="{ac}" 
        dataDescriptor="{new MyCustomTreeDataDescriptor()}"/>    
    <mx:Button label="add children" click="clickAddChildren()"/>
</mx:Application>
原文地址:http://livedocs.adobe.com/flex/201/html/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Book_Parts&file=about_dataproviders_057_15.html
<script language=JavaScript1.2 type=text/javascript> </script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值