Well, in case anyone else comes along, I thought I'd post my solution.  It
basically caches all the expanded nodes and the selected node, resets the
dataprovider, then restores those states.  There's a little flickering, but
it's minimal.  I wrote the functions recursively, but if you run into that
being a problem you could just rewrite it.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"; layout="vertical"
creationComplete="creationComplete()">
  <mx:Script>
    <![CDATA[
      import mx.events.ListEvent;
      import mx.collections.SortField;
      import mx.collections.Sort;
      import mx.collections.ArrayCollection;

      [Bindable] private var treedata:ArrayCollection = new
ArrayCollection([]);

      private function creationComplete():void
      {
        var sort:Sort = new Sort;
        sort.fields = [new SortField("label", true)];

        treedata.sort = sort;

        for (var i:int = 0; i < 4; i++)
        {
          var node:Object = {label:"parent"+i, children:new
ArrayCollection([])};
          for (var c:int = 0; c < 3; c++)
          {
            var child:Object = {label:"child"+c};
            node.children.addItem(child);
          }
          node.children.sort = sort;
          node.children.refresh();
          treedata.addItem(node);
        }

        treedata.refresh();
      }

      private function renameBtnClick():void
      {
        tree.editable = true;
        var e:ListEvent = new ListEvent(ListEvent.ITEM_EDIT_BEGINNING,
false, false, 0, tree.selectedIndex);
        tree.dispatchEvent(e);
      }

      private var editedItem:Object;
      private var expandedNodes:Array = [];

      private function renameEnd(e:ListEvent):void
      {
        tree.editable = false;
        editedItem = e.itemRenderer.data;
        callLater(resetTreedata);
      }

      private function resetTreedata():void
      {
        expandedNodes = [];
        getExpandedNodes(treedata);

        var nodeParentList:ArrayCollection = findParentList(editedItem,
treedata);

        nodeParentList.refresh();
        tree.dataProvider = treedata;

        callLater(expandAndSelect);
      }

      private function expandAndSelect():void
      {
        expandNodes(treedata);
        tree.selectedItem = editedItem;
      }

      private function findParentList(node:Object,
list:ArrayCollection):ArrayCollection
      {
        var index:int = list.getItemIndex(node);

        for each (var o:Object in list)
        {
          if (o == node)
            return list;

          if (o.children && o.children.length)
          {
            var result:ArrayCollection = findParentList(node, o.children);
            if (result)
              return result;
          }
        }

        return null;
      }

      private function getExpandedNodes(list:ArrayCollection):void
      {
        for each (var o:Object in list)
          if (tree.isItemOpen(o))
          {
            expandedNodes.push(o);
            if (o.children && o.children.length)
              getExpandedNodes(o.children);
          }
      }

      private function expandNodes(list:ArrayCollection):void
      {
        for each (var o:Object in list)
          if (expandedNodes.indexOf(o) != -1)
          {
            tree.expandItem(o, true);
            if (o.children && o.children.length)
              expandNodes(o.children);
          }
      }

    ]]>
  </mx:Script>
  <mx:Tree
    id="tree"
    dataProvider="{treedata}"
    width="200"
    height="400"
    editable="false"
    itemEditEnd="renameEnd(event)"
    />
    <mx:Button label="Rename" click="renameBtnClick()"/>
</mx:Application>


On Nov 28, 2007 1:19 PM, Pan Troglodytes <[EMAIL PROTECTED]> wrote:

> Well, that's really unfortunate, as I'm trying to deliver an application
> based on Flex 2 that has this behavior.  I'm going to try hacking something
> together to save/restore the tree layout after resetting the dataprovider.
> If anyone else has any suggestions, I'd really appreciate them.
>
>
> On Nov 28, 2007 11:38 AM, Alex Harui <[EMAIL PROTECTED]> wrote:
>
> >    Tree doesn't really support sorting.  We hope to provide an example
> > in 3.0 of how to get Tree to handle sorting
> >
> >  ------------------------------
> > *From:* [email protected] [mailto:[EMAIL PROTECTED] *On
> > Behalf Of *Pan Troglodytes
> > *Sent:* Wednesday, November 28, 2007 8:27 AM
> > *To:* flexcoders
> > *Subject:* [flexcoders] a tree that keeps sorted
> >
> >  I'm trying to build a tree (Flex 2) that keeps its nodes sorted, even
> > when you edit them.  I keep running into problems, though.  Here's the basic
> > app, without the auto-sorting:
> >
> > <?xml version="1.0" encoding="utf-8"?>
> > <mx:Application xmlns:mx=" http://www.adobe.com/2006/mxml";
> > layout="vertical" creationComplete="creationComplete()">
> >   <mx:Script>
> >     <![CDATA[
> >       import mx.collections.SortField;
> >       import mx.collections.Sort;
> >       import mx.collections.ArrayCollection ;
> >
> >       [Bindable] private var treedata:ArrayCollection =
> >         new ArrayCollection([
> >           {label:"node0"},
> >           {label:"node1"},
> >           {label:"node2"},
> >           {label:"node3"},
> >           {label:"node4"}
> >         ]);
> >
> >       private function creationComplete():void
> >       {
> >         var sort:Sort = new Sort;
> >         sort.fields = [new SortField("label", true)];
> >         treedata.sort = sort;
> >       }
> >     ]]>
> >   </mx:Script>
> >   <mx:Tree
> >     id="tree"
> >     dataProvider="{treedata}"
> >     width="200"
> >     editable="true"
> >     />
> > </mx:Application>
> >
> >
> > Okay, so that lets you click on the nodes and edit them.  What should be
> > done to get the nodes to re-sort after editing?  I've tried:
> >
> >     itemEditEnd="treedata.refresh()"
> >
> > Doesn't work, because when itemEditEnd has been called, the dataprovider
> > hasn't actually been updated.
> >
> >     itemEditEnd="callLater(treedata.refresh, [])"
> >
> > Sorta works, until renamed "node2" to "node" and then it just
> > disappears.  If you rename the last node to something that would make it the
> > first node, you get an error.
> >
> >       private function reload():void
> >       {
> >         treedata.refresh();
> >         tree.dataProvider = treedata;
> >       }
> >
> >     itemEditEnd="callLater(reload)"
> >
> > This works ok, until you have a node with children like:
> >     {label:"node0", children:new ArrayCollection([{label:"child-0-1"},
> > {label:"child-0-2"}])},
> > And you expand it before renaming "node4" to "node".  Then you get an
> > error.
> >
> > I've also tried this without using itemEditEnd and instead having the
> > node be a custom object that throws events.  I run into the same issues.
> > What's the "right" way to do something that should be a pretty simple task?
> >
> > --
> > Jason
> >  
> >
>
>
>
> --
> Jason




-- 
Jason

Reply via email to