14 Replies Latest reply on Jan 28, 2011 2:21 AM by cheng.wei

    datagrid itemrenderer layout problem

    cheng.wei

      Hi Guys,

       

      I am still struggling with datagrid itemRenderer. When dataProvider is updated, ItemRenderer's height randomly appears too high and sometimes datagrid contains unwanted rows. I have read Alex's blog "http://blogs.adobe.com/aharui/2010/10/mx-datagrid-list-and-variablerowheight.html#comment- 2885", and tried to apply his method, but still without a success. (i have set variableRowHeight to true)

      1. height is good at first.

      good.png

      2.problematic height after dataprovider is updated.

      problem.png

      3.no extra rows

      good2.png

      4.extra unwanted rows

      row_problem.png

       

      I have created a simple sample to demonstrate, but can not attach here.

       


      Could anybody help please?

       

       

      Cheers,

      Cheng Wei

        • 1. Re: datagrid itemrenderer layout problem
          cheng.wei Level 1

          Does anybody have idea. Really need help on this. I am stuck.

           

           

          Your help will be highly appreciated.

           

          Cheers,

          Cheng Wei

          • 2. Re: datagrid itemrenderer layout problem
            thailam

            can you post your code here so I can have a look. It's hard to tell with these images

            • 3. Re: datagrid itemrenderer layout problem
              cheng.wei Level 1

              Hi thailam,

               

              Thanks for your reply, it is hard to paste the code here, but i will have try.

               

              DataGridTest.mxml

              <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
                                          xmlns:s="library://ns.adobe.com/flex/spark" 
                                          xmlns:mx="library://ns.adobe.com/flex/mx"
                                          creationComplete="installTimer()" width="800" height="600">
                   <fx:Declarations>
                        <fx:String id="html0">
                             <![CDATA[
                             <html><style type="text/css"> body{     text-align:left;     font-family: verdana;     font-size: 10px;}</style><body><b>Half & Half</b><br/><b><i>Base:</i></b><br/>Dominator<br/><b><i>Size:</i></b><br/>Meduim<br/><b><i>Toppings:</i></b><br/><b>1H: </b><br/>+Pizza Sauce, ++Ground Beef, ++Mozzarella Cheese, -Green Peppers<br/><b>2H: </b><br/>++Pizza Sauce, ++Ground Beef, +Mozzarella Cheese, -Green Peppers</body></html>
                             ]]>
                        </fx:String>
                        <fx:String id="html1">
                             <![CDATA[
                             <html><style type="text/css"> body{     text-align:left;     font-family: verdana;     font-size: 10px;}</style><body><b>Ben & Jerry's</b><br/>500ml tub</body></html>
                             ]]>
                        </fx:String>
                        <fx:String id="html2">
                             <![CDATA[
                             <html><style type="text/css"> body{     text-align:left;     font-family: verdana;     font-size: 10px;}</style><body><b>Party Pack</b><br/><b><i>Drink</i></b><br/>Coke Zero<br/><b><i>Italian style folded pizza</i></b><br/>Barbeque, Garlic & Tomato<br/></body></html>
                             ]]>
                        </fx:String>
                        <fx:String id="html3">
                             <![CDATA[
                             <html><style type="text/css"> body{     text-align:left;     font-family: verdana;     font-size: 10px;}</style><body><b>Half & Half</b><br/><b><i>Base:</i></b><br/>Dominator<br/><b><i>Size:</i></b><br/>Meduim<br/><b><i>Toppings:</i></b><br/><b>1H: </b><br/>+Pizza Sauce, ++Ground Beef, ++Mozzarella Cheese, -Green Peppers<br/><b>2H: </b><br/>++Pizza Sauce, ++Ground Beef, +Mozzarella Cheese, -Green Peppers</body></html>
                             ]]>
                        </fx:String>
                        <fx:String id="html4">
                             <![CDATA[
                             <html><style type="text/css"> body{     text-align:left;     font-family: verdana;     font-size: 10px;}</style><body><b>Ben & Jerry's</b><br/>500ml tub</body></html>
                             ]]>
                        </fx:String>
                        <fx:String id="html5">
                             <![CDATA[
                             <html><style type="text/css"> body{     text-align:left;     font-family: verdana;     font-size: 10px;}</style><body><b>Party Pack</b><br/><b><i>Drink</i></b><br/>Coke Zero<br/><b><i>Italian style folded pizza</i></b><br/>Barbeque, Garlic & Tomato<br/></body></html>
                             ]]>
                        </fx:String>
                        <fx:String id="html6">
                             <![CDATA[
                             <html><style type="text/css"> body{     text-align:left;     font-family: verdana;     font-size: 10px;}</style><body><b>Half & Half</b><br/><b><i>Base:</i></b><br/>Dominator<br/><b><i>Size:</i></b><br/>Meduim<br/><b><i>Toppings:</i></b><br/><b>1H: </b><br/>+Pizza Sauce, ++Ground Beef, ++Mozzarella Cheese, -Green Peppers<br/><b>2H: </b><br/>++Pizza Sauce, ++Ground Beef, +Mozzarella Cheese, -Green Peppers</body></html>
                             ]]>
                        </fx:String>
                        <fx:String id="html7">
                             <![CDATA[
                             <html><style type="text/css"> body{     text-align:left;     font-family: verdana;     font-size: 10px;}</style><body><b>Ben & Jerry's</b><br/>500ml tub</body></html>
                             ]]>
                        </fx:String>
                        <fx:String id="html8">
                             <![CDATA[
                             <html><style type="text/css"> body{     text-align:left;     font-family: verdana;     font-size: 10px;}</style><body><b>Party Pack</b><br/><b><i>Drink</i></b><br/>Coke Zero<br/><b><i>Italian style folded pizza</i></b><br/>Barbeque, Garlic & Tomato<br/></body></html>
                             ]]>
                        </fx:String>
                        <s:ArrayCollection id="arrayCollection">
                             <fx:Object name="html0" content="{html0}"/>
                             <fx:Object name="html1" content="{html1}"/>
                             <fx:Object name="html2" content="{html2}"/>
                             <fx:Object name="html3" content="{html3}"/>
                             <fx:Object name="html4" content="{html4}"/>
                             <fx:Object name="html5" content="{html5}"/>
                             <fx:Object name="html6" content="{html6}"/>
                             <fx:Object name="html7" content="{html7}"/>
                             <fx:Object name="html8" content="{html8}"/>
                        </s:ArrayCollection>
                        <!-- Place non-visual elements (e.g., services, value objects) here -->
                   </fx:Declarations>
                   <fx:Script>
                        <![CDATA[
                             import mx.collections.ArrayCollection;
                             import mx.events.CollectionEvent;
                             private function installTimer():void
                             {
                                  var timer:Timer = new Timer(3000);
                                  timer.addEventListener(TimerEvent.TIMER, dataProviderUpdate);
                                  timer.start();
                                  
                                  dataGrid.addEventListener(CollectionEvent.COLLECTION_CHANGE, dataProviderChange);
                             }
                             private function dataProviderChange(event:CollectionEvent):void
                             {
                                  sizeDGExactly();
                             }
                             private function sizeDGExactly():void
                             {
                                  var dg:DataGrid = dataGrid;
                                  if (dg)
                                  {
                                       dg.height = dg.measureHeightOfItems(-1, // have start with index = -1 so header gets measured 
                                            dg.dataProvider.length + 1) // have to ask for one extra row so header gets measured
                                            + dg.viewMetrics.top // add in top border
                                            + dg.viewMetrics.bottom; // and bottom border
                                  }
                             }
                             private function dataProviderUpdate(event:TimerEvent):void
                             {
                                  var seedOrders:Array = [5,7,2,0,8,4,3,6,1];
                                  var dataCollection:ArrayCollection = new ArrayCollection();
                                  for(var i:int=9; i>0; i--)
                                  {
                                       var index:int = RandomUtils.nextInt(i);
                                       var order:int = seedOrders.splice(index, 1);
                                       dataCollection.addItem(arrayCollection.getItemAt(order));
                                  }
                                  dataGrid.dataProvider = dataCollection;
                             }
                        ]]>
                   </fx:Script>
                   <s:Scroller horizontalScrollPolicy="off" width="100%" height="500">
                        <s:VGroup horizontalAlign="justify" width="100%" height="100%">
                   <mx:DataGrid variableRowHeight="true" id="dataGrid">
                        <mx:columns>
                             <mx:DataGridColumn headerText="Name" dataField="name"/>
                             <mx:DataGridColumn width="400" headerText="HTML" dataField="content" editable="false"
                                                    itemRenderer="HTMLRenderer"/>
                        </mx:columns>
                   </mx:DataGrid>
                        </s:VGroup>
                   </s:Scroller>
              </s:WindowedApplication>
              
              HTMLRenderer.as
              package 
              {
                   import mx.binding.utils.BindingUtils;
                   import mx.containers.HBox;
                   import mx.controls.HTML;
                   import mx.controls.dataGridClasses.DataGridListData;
                   import mx.controls.listClasses.BaseListData;
                   import mx.controls.listClasses.IDropInListItemRenderer;
                   import mx.controls.listClasses.IListItemRenderer;
                   import mx.controls.listClasses.MXItemRenderer;
                   import mx.events.FlexEvent;
                   import mx.logging.ILogger;
                   import mx.logging.Log;
                   
                   import spark.components.HGroup;
              
                   public class HTMLRenderer extends HBox implements IDropInListItemRenderer,IListItemRenderer
                   {
                        private var _htmlControl:HTML;
                        private var _listData:DataGridListData;
                        private var log:ILogger;
                        
                        public function HTMLRenderer()
                        {
                             log = Log.getLogger("HTMLRenderer");
                        }
                        public function get listData():BaseListData
                        {
                             return _listData;
                        }
                        
                        public function set listData(value:BaseListData):void
                        {
                             _listData = DataGridListData(value);
                        }
                        override public function set data(value:Object):void
                        {
                             var newText:String = "";
                             if(value != null)
                             {
                                  var fieldValue:* = value[(listData as DataGridListData).dataField];
                                  if(fieldValue is String)
                                  {
                                       newText = fieldValue as String;
                                  }
                             }
                             _htmlControl.htmlText = newText;
                             log.debug(newText);
                             
                             super.data = value;
                             dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
                        }
                        override protected function createChildren():void
                        {
                             _htmlControl = new HTML();
                             _htmlControl.percentWidth = 100;
                             _htmlControl.paintsDefaultBackground = false;
                             
                             var group:HGroup = new HGroup();
                             group.addElement(_htmlControl);
                             BindingUtils.bindProperty(group, "width", this, "explicitWidth");
                             //group.percentWidth = 100;
                             group.paddingBottom = 5;
                             group.paddingLeft = 5;
                             group.paddingRight = 5;
                             addChild(group);
                        }
                   }
              }
              
              
              
              
              • 4. Re: datagrid itemrenderer layout problem
                cheng.wei Level 1

                There are two class files above.

                 

                Appreciate your help. If you want the source code, please let me know.

                 

                Many thanks,

                Cheng Wei

                • 5. Re: datagrid itemrenderer layout problem
                  Flex harUI Adobe Employee

                  You should bind the explicitWidth of the HTML to the explicitWidth of the

                  renderer.

                  • 6. Re: datagrid itemrenderer layout problem
                    cheng.wei Level 1

                    Thanks for your reply.

                     

                    There is no difference with explicitWidth. If you want sample app i created, please let me know and i will send you.

                     

                    Cheers,

                    Cheng Wei

                    • 7. Re: datagrid itemrenderer layout problem
                      Flex harUI Adobe Employee

                      Just post the code for the renderer.

                      • 8. Re: datagrid itemrenderer layout problem
                        cheng.wei Level 1

                        Thanks a lot. The only change i made was to bind to explicitWidth as you suggested.

                        public class HTMLRenderer extends HBox implements IDropInListItemRenderer,IListItemRenderer
                             {
                                  private var _htmlControl:HTML;
                                  private var _listData:DataGridListData;
                                  private var log:ILogger;
                                  
                                  public function HTMLRenderer()
                                  {
                                       log = Log.getLogger("HTMLRenderer");
                                  }
                                  public function get listData():BaseListData
                                  {
                                       return _listData;
                                  }
                                  
                                  public function set listData(value:BaseListData):void
                                  {
                                       _listData = DataGridListData(value);
                                  }
                                  override public function set data(value:Object):void
                                  {
                                       var newText:String = "";
                                       if(value != null)
                                       {
                                            var fieldValue:* = value[(listData as DataGridListData).dataField];
                                            if(fieldValue is String)
                                            {
                                                 newText = fieldValue as String;
                                            }
                                       }
                                       _htmlControl.htmlText = newText;
                                       log.debug(newText);
                                       
                                       super.data = value;
                                       dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
                                  }
                                  override protected function createChildren():void
                                  {
                                       _htmlControl = new HTML();
                                       _htmlControl.percentWidth = 100;
                                       _htmlControl.paintsDefaultBackground = false;
                                       
                                       var group:HGroup = new HGroup();
                                       group.addElement(_htmlControl);
                                       BindingUtils.bindProperty(group, "explicitWidth", this, "explicitWidth");
                                       //group.percentWidth = 100;
                                       group.paddingBottom = 5;
                                       group.paddingLeft = 5;
                                       group.paddingRight = 5;
                                       addChild(group);
                                  }
                             }
                        
                        • 9. Re: datagrid itemrenderer layout problem
                          Flex harUI Adobe Employee

                          I would consider getting rid of the Group, overriding measure() and setting

                          the size and position of the HTMLControl based on the renderer's

                          explicitWidth, factoring in the padding.

                           

                          Do not use percentWidth on the HTMLControl.  You did not bind to the

                          HTMLControl, you bound to the group.

                          • 10. Re: datagrid itemrenderer layout problem
                            cheng.wei Level 1

                            Many thanks for your time. i have tried directly bind to HTMLRenderer, but there is no difference.

                            I have not tried the other idea you mentioned with measure method, could you show me how to do?

                            The new code is below:

                            public class HTMLRenderer extends HBox implements IDropInListItemRenderer,IListItemRenderer
                                 {
                                      private var _htmlControl:HTML;
                                      private var _listData:DataGridListData;
                                      private var log:ILogger;
                                      
                                      public function HTMLRenderer()
                                      {
                                           log = Log.getLogger("HTMLRenderer");
                                      }
                                      public function get listData():BaseListData
                                      {
                                           return _listData;
                                      }
                                      
                                      public function set listData(value:BaseListData):void
                                      {
                                           _listData = DataGridListData(value);
                                      }
                                      override public function set data(value:Object):void
                                      {
                                           var newText:String = "";
                                           if(value != null)
                                           {
                                                var fieldValue:* = value[(listData as DataGridListData).dataField];
                                                if(fieldValue is String)
                                                {
                                                     newText = fieldValue as String;
                                                }
                                           }
                                           _htmlControl.htmlText = newText;
                                           log.debug(newText);
                                           
                                           super.data = value;
                                           dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
                                      }
                                      override protected function createChildren():void
                                      {
                                           _htmlControl = new HTML();
                                           //_htmlControl.percentWidth = 100;
                                           BindingUtils.bindProperty(_htmlControl, "explicitWidth", this, "explicitWidth");
                                           _htmlControl.paintsDefaultBackground = false;
                                           
                                           /*
                                           var group:HGroup = new HGroup();
                                           group.addElement(_htmlControl);
                                           BindingUtils.bindProperty(group, "explicitWidth", this, "explicitWidth");
                                           //group.percentWidth = 100;
                                           group.paddingBottom = 5;
                                           group.paddingLeft = 5;
                                           group.paddingRight = 5;
                                           */
                                           addChild(_htmlControl);
                                      }
                                 }
                            
                            • 11. Re: datagrid itemrenderer layout problem
                              cheng.wei Level 1

                              Hi Sir or Madam, i have sent you a private message, please have a check.

                               

                              Cheers,

                              Cheng Wei

                              • 12. Re: datagrid itemrenderer layout problem
                                Flex harUI Adobe Employee

                                Probably something like:

                                 

                                    override protected function measure():void

                                    {

                                        _htmlControl.width = explicitWidth - 10;

                                        _htmlControl.x = 5;

                                        _htmlControl.y = 5;

                                        super.measure();

                                        measuredHeight += 5;    // bottom padding

                                    }

                                • 13. Re: datagrid itemrenderer layout problem
                                  cheng.wei Level 1

                                  Appologize for the late reply. i will try that out and get back to you.

                                   

                                  Cheers,

                                  Cheng

                                  • 14. Re: datagrid itemrenderer layout problem
                                    cheng.wei Level 1

                                    Hi, still this does not help. make no difference. Any other thoughts, or i think it is better that i send you the code?

                                     

                                    Thanks for your time.

                                    Cheng