I’ve a tree control with checkboxes that uses the control from http://www.sephiroth.it/file_detail.php?id=151#
Somehow I can’t get the control to update when I change the dataProvider (i.e. by clicking a checkbox) the only way I can get it to update is to use the scrollbar. How do I force the update? I’ve tried all possible methods I can figure out? (see update below)
Also how can I reset the Tree (collpasing all nodes, scroll to the top in a large tree)?
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); } } } }
I’ve found the Tree control a little touchy in Flex. The way I ended up forcing a redraw was to disconnect the dataProvider and reconnect it, then force validation, something a bit like this :
I guess this incidentally answers the second part of your question since all you’d have to do is null out the openItems collection and set the verticalScrollPosition to 0.