6 Replies Latest reply on Sep 18, 2008 6:09 AM by peterh8234

    Items in Tree control move around when data is submitted using custom ItemRenderer

    Level 7
      I'm working on a Tree control with an XMLListCollection as its dataProvider.
      The dataProvider has information looking like this :
      quote:


      <?xml version='1.0' encoding='utf-8'?>
      <INFO>
      <FIELD label="STR_USER_NAME"
      type="text"
      value=""
      >
      </FIELD>
      <FIELD label="STR_USER_EMAIL"
      type="text"
      value=""
      >
      </FIELD>
      <FIELD label="STR_OPTIONAL"
      type="branch"
      value="0"
      >
      <FIELD label="STR_USER_ADDRESS"
      type="text"
      value=""
      >
      </FIELD>
      <FIELD label="STR_USER_POSTAL_CODE"
      type="text"
      value=""
      >
      </FIELD>
      </FIELD>
      </INFO>


      So in the Tree control I'd like the information to show up with a label and
      an
      editable textbox for each item :

      [Label] [textbox]

      To do this I made a tree like this :
      quote:


      <mx:Tree id="userTree"
      editable="true"
      rendererIsEditor="true"
      editorDataField="curVal"
      itemRenderer="{new ClassFactory(ItemRendererUser)}"
      itemEditEnd="e_ProcessData(event);"
      dataDescriptor="{new DataDescriptorUsers()}"
      showRoot="false"
      verticalScrollPolicy="{ScrollPolicy.AUTO}"
      />


      where the e_ProcessData() function looks like this (I used
      http://livedocs.adobe.com/flex/201/html/wwhelp/wwhimpl/js/html/wwhelp.htm?href=c
      elleditor_073_16.html#202105 as a guide) :
      quote:


      public function e_ProcessData(event:ListEvent):void
      {
      event.preventDefault();

      userTree.editedItemRenderer.data.@value =
      ItemRendererUsers(event.currentTarget.itemEditorInstance).curVal;

      userTree.destroyItemEditor();

      userTree.dataProvider.notifyItemUpdate(userTree.editedItemRenderer);
      } // END OF e_ProcessData()


      I attached the rest of the files because they're a little bit longer.


      When I run the program, the data shows up fine when it is initialized the
      very
      first time, and I made a test button that just dumps the contents of the
      dataProvider in a trace statement to verify that the data has been set
      properly.
      The problem I've run into is whenever the textfield is edited, the item
      that
      I've selected jumps around the list.

      For example, if I edit the item "STR_USER_NAME" after I finish the edit, it
      will move from the very first position in the Tree to the bottom of the
      Tree.
      I traced the contents of the dataProvider and the dataProvider structure
      stays
      the same, with the "STR_USER_NAME" at the top, but if I look at the flex app
      in
      the web browser, its position is at the bottom of the Tree.

      This happens for every other item I try to edit... I read in the
      documentation
      that the ItemRenderers are recycled, so it means I should be checking to
      make
      sure the initial states are covered, but I'm not sure how this affects my
      application.

      Can anyone help me out with this ? Its very confusing - I've tried making
      an
      ItemRenderer using pure actionscript, mxml and the combination you see in
      this
      example and I always end up with the same behaviour - So I must be missing
      something critical...

      // ItemRendererUsers.mxml
      <?xml version="1.0" encoding="utf-8"?>
      <mx:Canvas xmlns:mx=" http://www.adobe.com/2006/mxml"
      verticalScrollPolicy="{ScrollPolicy.OFF}"
      horizontalScrollPolicy="{ScrollPolicy.OFF}"
      creationComplete="initItemRendererUsers();"
      >

      From my FAQ:

      Q: I've created a custom itemRenderer component to use in a List
      based component (Datagrid, TileList, HorizontalList, etc.). When my List
      first displays, everything looks fine, but when I scroll it or change the
      dataProvider, some of the itemRenderers show values or formatting that
      aren't right. How do I fix this?

      A: List-based components don't draw a renderer for every item in the
      dataProvider. Instead, they create enough to display what is on screen now,
      plus one or two more waiting in the wings. This means they recycle the
      renderers rather than creating new ones when you change dataProvider or
      scroll up and down. When you use a creationComplete event to set up the
      itemRenderer, that event doesn't happen again when the renderer is used for
      a different set of data. The solution to this is to override the set data
      protected function that most components have.

      For more information, check out the following resources:
      http://www.adobe.com/devnet/flex/articles/itemrenderers_pt1.html?devcon=f1
      http://blogs.adobe.com/aharui/2007/03/thinking_about_item_renderers_1.html



      Please note, I post this FAQ weekly, and you can find a permanent copy of it
      here http://www.magnoliamultimedia.com/flex_examples/Amys_Flex_FAQ.pdf ;-)