2009-01-06 58 views
6

我曾与复选框树控件使用来自http://www.sephiroth.it/file_detail.php?id=151#的Flex:更新树控制

控制不知怎的,我不能得到控制,当我改变数据提供程序更新(通过点击复选框IE)的只有这样才能让它更新就是使用滚动条。我如何强制更新?我尝试了所有可能的方法,我可以弄清楚吗? (请参阅下面的更新)

另外我该如何重置树(collpasing all nodes,scroll to a 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); 
      } 
     } 

    }  

} 

回答

20

我发现树控件在Flex中有点敏感。我最终迫使重绘方法是断开数据提供程序并重新连接,然后强制验证,东西有点像这样:

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.

+0

谢谢!你今天是我的英雄! – 2009-01-07 09:37:37

+0

2年后,这仍然有用!真棒! – 2011-07-08 10:34:23

0

我对这个解决方案有一些小问题,var scrollPosition:Number = tree.verticalScrollPosition;是不断0?

1

你可能会遇到另一个问题:每当你检查一个项目时,树会滚动到顶部,这只是令人讨厌的。为了解决这个问题,你应该这样更新TreeCheckBox.as文件: in function checkHandler: private function checkHandler(event:TreeEvent):void;

评论commitProperties();呼叫。

现在它应该很好。

干杯。