Flex:更新Tree控件

时间:2009-01-06 11:12:06

标签: flex actionscript-3

我有一个树形控件,其复选框使用http://www.sephiroth.it/file_detail.php?id=151#

中的控件

当我更改dataProvider(即通过单击复选框)时,我无法让控件更新,我可以让它更新的唯一方法是使用滚动条。如何强制更新?我已经尝试过所有可能的方法了吗? (见下面的更新)

另外如何重置树(拼写所有节点,滚动到大树的顶部)?

package offerta.monkeywrench.components
{

    import offerta.monkeywrench.components.componentClasses.TreeCheckBoxItemRenderer;

    import mx.collections.ArrayCollection;

    import mx.events.TreeEvent;

    public class WatchTree extends TreeCheckBox
    {

        public var idProperty:String;

        public var watchFactory:Function;

        private var _wSet:Boolean = false;

        /* clientId: */

        private var _clientId:String;

        [Bindable]
        public function get clientId():String
        {
            return _clientId;
        }

        public function set clientId(value:String):void
        {
            this._clientId = value;
        }

        /* //clientId */

        /* watching: */

        private var _watching:ArrayCollection;

        [Bindable]
        public function set watching(value:ArrayCollection):void
        {
            this._watching = value;
        }

        public function get watching():ArrayCollection
        {
            return this._watching;    
        }

        /* //watching */

        override public function initialize() :void
        {
            super.initialize();
            addEventListener("itemCheck", onItemCheck, false, 0, true);
        }

        private function isWatching(id:String):Boolean
        {
            for each(var w:Object in this._watching)
            {
                if(w[this.idProperty]==id) return true;
            }
            return false;
        }

        private function onItemCheck(event:TreeEvent):void
        {
            var item:Object = event.item as Object;
            var currentValue:uint = (event.itemRenderer as TreeCheckBoxItemRenderer).checkBox.checkState;
            if(item.children==null)
            {
                currentValue==2 ? addWatch(item.Id) : removeWatch(item.Id);
            }
            else
            {
                for each(var x:Object in item.children)
                {
                    currentValue==2 ? addWatch(x.Id) : removeWatch(x.Id);
                }
            }
            updateParents(item, currentValue);
            updateChilds(item, currentValue);
            this.dataProvider.refresh();
            super.invalidateProperties();
            super.invalidateDisplayList();
            super.updateDisplayList(this.unscaledWidth, this.unscaledHeight);
        }

        private function updateParents(item:Object, value:uint):void
        {
            var checkValue:String = (value == ( 1 << 1 | 2 << 1 ) ? "2" : value == ( 1 << 1 ) ? "1" : "0");
            var parentNode:Object = item.parent;
            if(parentNode)
            {
                for each(var x:Object in parentNode.children)
                {
                    if(x.checked != checkValue)
                    {
                        checkValue = "2"
                    }
                }
                parentNode.checked = checkValue;
                updateParents(parentNode, value);
            }
        }

        private function updateChilds(item:Object, value:uint):void
        {
            var middle:Boolean = (value&2<<1)==(2<<1);

            if(item.children!=null && item.children.length>0&&!middle)
            {
                for each(var x:Object in item.children)
                {
                    x.checked = value == (1<<1|2<<1) ? "2" : value==(1<<1) ? "1" : "0";
                    updateChilds(x, value);
                }
            }
        }

        private function addWatch(id:String):void
        {
            if(isWatching(id)) return;
            this._watching.addItem(this.watchFactory(id, this.clientId));
        }

        private function removeWatch(id:String):void
        {
            for(var i:int=0, n:int=this._watching.length; i<n; ++i)
            {
                if(this._watching[i][this.idProperty]==id)
                {
                    this._watching.removeItemAt(i);
                    return;
                }
            }
        }

        public function update(__watching:ArrayCollection, __clientId:String):void
        {
            clientId = __clientId;
            watching = __watching;
            if(this.dataProvider!=null)
            {
                var ws:ArrayCollection = ArrayCollection(this.dataProvider);
                for each(var group:Object in ws)
                {
                    var count:int = 0;
                    for each(var child:Object in group.children)
                    {
                        if(isWatching(child.Id))
                        {
                            child.checked = "1";
                            count++;
                        }
                    }
                    group.checked = (count==0 ? "0" : (count==group.children.length ? "1" : "2"));
                }
                this._wSet = false;

                var dp:ArrayCollection = ArrayCollection(this.dataProvider);
                dp.refresh();
                super.invalidateProperties();
                super.invalidateDisplayList();
                super.updateDisplayList(this.unscaledWidth, this.unscaledHeight);

                //scroll up the list???

                //collapse? (doesn't work)
                this.expandItem(null, false);
            }
        }

    }       

}

3 个答案:

答案 0 :(得分:20)

我发现Tree控件在Flex中有点敏感。我最终强制重绘的方法是断开dataProvider并重新连接,然后强制验证,有点像这样:

private function forceRedraw(tree:Tree, dataProvider:Object):void
{
    var scrollPosition:Number = tree.verticalScrollPosition;
    var openItems:Object = tree.openItems;
    tree.dataProvider = dataProvider;
    tree.openItems = openItems;
    tree.validateNow();
    tree.verticalScrollPosition = scrollPosition;
}

我想这偶然会回答你问题的第二部分,因为你所要做的就是将openItems集合归零并将verticalScrollPosition设置为0.

答案 1 :(得分:1)

您可能还有另一个问题:无论何时检查项目,树都会滚动到顶部,这很烦人。要解决此问题,您应该以这种方式更新TreeCheckBox.as文件: 在函数checkHandler中:   private function checkHandler(event:TreeEvent):void;

评论commitProperties();调用

现在它应该运作良好。

干杯。

答案 2 :(得分:0)

这个解决方案我遇到了一些小问题,var scrollPosition:Number = tree.verticalScrollPosition;经常是0 ??