2009-01-06 28 views
6

Tôi đã một điều khiển cây với hộp kiểm có sử dụng điều khiển từ http://www.sephiroth.it/file_detail.php?id=151#Flex: Cập nhật một điều khiển Tree

Bằng cách nào đó tôi không thể nhận sự kiểm soát để cập nhật khi tôi thay đổi dataProvider (tức là bằng cách nhấp vào hộp kiểm) các cách duy nhất tôi có thể làm cho nó cập nhật là sử dụng thanh cuộn. Làm cách nào để bắt buộc cập nhật? Tôi đã thử tất cả các phương pháp có thể tôi có thể tìm ra? (xem cập nhật bên dưới)

Ngoài ra làm cách nào tôi có thể đặt lại cây (thu thập tất cả các nút, cuộn lên trên cùng trong một cây lớn)?

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); 
      } 
     } 

    }  

} 

Trả lời

20

Tôi đã tìm thấy điều khiển Tree một chút nhạy cảm trong Flex. Con đường tôi đã kết thúc buộc một vẽ lại là để ngắt kết nối và kết nối lại dataProvider nó, sau đó buộc xác nhận, một chút gì đó như thế này:

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; 
}

Tôi đoán đây tình cờ trả lời phần thứ hai của câu hỏi của bạn vì tất cả các bạn muốn phải làm là vô hiệu hóa bộ sưu tập openItems và đặt verticalScrollPosition thành 0.

+0

Cảm ơn! Bạn là anh hùng của tôi hôm nay! –

+0

2 năm sau và điều này vẫn hữu ích! tuyệt vời! –

+1

@RoopeshShenoy: Thực hiện điều đó! – Viktor

0

Tôi đã gặp một số vấn đề nhỏ với giải pháp này, var scrollPosition: Number = tree.verticalScrollPosition; liên tục 0 ??

+0

Nó phụ thuộc vào số lượng vật phẩm bạn có trong cây. Bạn có một cây lớn đang được hiển thị và bạn có thực sự cuộn khi cố gắng vẽ lại không? – inferis

+0

Có, ngay cả khi Cây được cuộn dọc thì VerticalScrollPosition vẫn là 0. –

1

Bạn có thể có một vấn đề khác: bất cứ khi nào bạn kiểm tra một mục cây cuộn lên đầu và điều này chỉ gây phiền toái. Để giải quyết vấn đề này, bạn nên cập nhật tệp TreeCheckBox.as theo cách này: trong chức năng checkHandler: chức năng riêng checkHandler (sự kiện: TreeEvent): void;

nhận xét commitProperties(); gọi điện.

Bây giờ, nó sẽ hoạt động tốt.

Chúc mừng.

Các vấn đề liên quan