16 Replies Latest reply on Dec 3, 2008 11:53 AM by nate-digg

    Autosize Datagrid columns

    jkPatrick05
      Searched around and didn't see a definitive answer on this and it's the only thing from keeping me from considering Flex Builder as an ultimate solution for me.

      I have a Datagrid that initially contains 10 columns.
      The datagrid is populated via PHP through queries to a MySQL database.
      The resultant data in each cell in the datagrid can vary in size from empty to > 200 chars in length; so in a nutshell, each is simply dynamic in size.

      What I am hoping to achieve in detail:

      * The entire Datagrid will shrink and grow in size dependent on the content of its respective cell contents.
      * Each Column will be no smaller than the size of the HeaderText, even if the DataField is empty.
      * Each Column should size itself dynamically should the contents of the DataField be larger than it's respective HeaderText.
      * The HeaderText and also DataField data can wordwrap but not break apart whole words. eg. "Flex Builder Two" should not result in "Flex Bui" on line 1 and "lder Two" on line 2.

      What I basically need is a Datagrid setup where each column is auto-sized dependent on the size of it's largest contents.

      Is what I am looking for achievable natively with Flex Builder or are there perhaps other options?
        • 1. Re: Autosize Datagrid columns
          michael_ramirez44 Level 1
          Use the labelFunction.

          dg.labelFunction = columnText;

          private function columnText(item:Object,column:DataGridColumn):String
          {
          var colText:String = item[column.dataField];

          if( colText.length > column.headerText.length )
          {
          column.width = colText.length;
          }

          return colText;
          }
          • 2. Re: Autosize Datagrid columns
            michael_ramirez44 Level 1
            I just tested the code I had posted earlier and it does not work. I think it has to do with making DataGridColumn changes. I will try editing the columns property and rebinding it with the change.
            • 3. Autosize Datagrid columns
              michael_ramirez44 Level 1
              The following code works. The problem was that the text length is not directly related to the column width. The default column with of 100 can fit about 15 characters. So I needed to multiply the text length by 7 and if that number is greater then 100 adjust the column width. This is why I like responding to these post because I learn so much from trying to solve other people's problems.

              private function columnText(item:Object,column:DataGridColumn):String
              {
              var colText:String = item[column.dataField];

              if( (colText.length * 7) > column.width )
              {
              column.width = colText.length * 7;
              }

              return colText;
              }
              • 4. Re: Autosize Datagrid columns
                jakelove007
                sorry, I'm brand new to flex. How do I use this function on the datagrid?
                thanks
                • 5. Re: Autosize Datagrid columns
                  michael_ramirez44 Level 1
                  By column: dgColumn is you DataGridColumn

                  dgColumn.labelFunction = columnText;

                  By grid: dg is your DataGrid

                  dg.labelFunction = columnText;
                  • 6. Re: Autosize Datagrid columns
                    arrowCai
                    I also encountered this problem during my training.
                    I tried your code, actually it worked just when the first item(one record in XMLList)'s text length is the longest of all the items. You can try modifying your dataProvider, to that the second or third of text's length in record is the longest and you will find the problem rise.
                    I'm a brand new but In my view, the head line of datagrid also contain a datagridcolumn, so if we can also set the hearcolumn's width to properly width, we will solve this problem perfectly.
                    Best Regard!
                    Cai
                    • 7. Re: Autosize Datagrid columns
                      Peocc
                      It's really strange only when the first column width is the largest it works properly, otherwise the last column is not shown or the width is smaller than specified. Can someone explain the problem?
                      • 8. Re: Autosize Datagrid columns
                        JCFlex2
                        How about this?

                        private function optimizeColumnWidths (dg:DataGrid):void
                        {
                        var dgCol:DataGridColumn;
                        var renderer:UITextField;
                        var tf:TextFormat;
                        var col:int;

                        if (dg.columnCount > 0 && dg.dataProvider != null)
                        {
                        // initialize widths array
                        var widths:Array = new Array (dg.columnCount);
                        for (col = 0; col < widths.length; ++col)
                        {
                        widths[col] = -1;
                        }

                        // go through each data item in the grid, estimate
                        // the width of the text in pixels
                        for each (var item:Object in dg.dataProvider)
                        {
                        for (col = 0; col < widths.length; ++col)
                        {
                        // TODO: it's ok to reuse renderer, but I chose not
                        // to for safety reasons. Optimize if needed.
                        renderer = new DataGridItemRenderer();

                        // Must add to datagrid as child so that it inherits
                        // properties essential for text width estimation,
                        // such as font size
                        dg.addChild(renderer);

                        dgCol = dg.columns[col] as DataGridColumn;
                        renderer.text = dgCol.itemToLabel(item);
                        widths[col] = Math.max(renderer.measuredWidth + 10, widths[col]);

                        // remove renderer from datagrid when we're done
                        dg.removeChild(renderer);
                        }
                        }

                        // go through headers in the grid, estimate the width of
                        // the text in pixels, assuming the text is bold
                        for (col = 0; col < widths.length; ++col)
                        {
                        // TODO: it's ok to reuse renderer, but I chose not
                        // to for safety reasons. Optimize if needed.
                        renderer = new DataGridItemRenderer();

                        // Must add to datagrid as child so that it inherits
                        // properties essential for text width estimation,
                        // such as font size
                        dg.addChild(renderer);

                        dgCol = dg.columns[col] as DataGridColumn;
                        renderer.text = dgCol.headerText;

                        tf = renderer.getTextFormat();
                        tf.bold = true;
                        renderer.setTextFormat (tf);

                        widths[col] = Math.max(renderer.measuredWidth + 25, widths[col]);

                        // remove renderer from datagrid when we're done
                        dg.removeChild(renderer);
                        }

                        // set width of columns to determined values
                        for (col = 0; col < widths.length; ++col)
                        {
                        if (widths[col] != -1)
                        {
                        trace ("Optimized width of col " + col + " to " + widths[col]);
                        dg.columns[col].width = widths[col];
                        }
                        }
                        }
                        }
                        • 9. Autosize Datagrid columns
                          Sjoerd_ Level 1
                          Wow, that function works like a charm, but only when pressing a button to activate it.

                          Which event do i need to use when my dataprovider changes ?

                          DataGrid.datachange
                          DataGrid.render

                          Those wont work.

                          Annoying about that earlier function from "michael_ramirez44" is that when you resize a colum (by mouse) the labelfunction also fires. By then it displays your columnheaders wrong.

                          -Sjoerd
                          • 10. Re: Autosize Datagrid columns
                            DeusAquilus
                            Dude, create a text field, fill it with the longest string and measure its length.
                            • 11. Re: Autosize Datagrid columns
                              RobX82
                              quote:

                              Originally posted by: Sjoerd_
                              Wow, that function works like a charm, but only when pressing a button to activate it.

                              Which event do i need to use when my dataprovider changes ?

                              DataGrid.datachange
                              DataGrid.render

                              Those wont work.

                              Annoying about that earlier function from "michael_ramirez44" is that when you resize a colum (by mouse) the labelfunction also fires. By then it displays your columnheaders wrong.

                              -Sjoerd


                              I am looking to get this function working with my datagrid also without any luck. Did you happen to find a way to have this fire when the grid is populated?
                              • 12. Autosize Datagrid columns
                                chris12296
                                If you populate your datagrid from the results of an HTTPService, you can call the function in the handler function for the result event of the HTTPService. Flex 3 is event driven so try to think of an event that will always occur before the datagrid will have data and call the function from that event handler.
                                • 13. Re: Autosize Datagrid columns
                                  angie_mc
                                  This is great, exactly what I've been looking for for the AdvancedDataGrid, thanks for providing this. I've noticed that I also need to update the width of the grid as well, not sure whether this is an AdvancedDataGrid thing or not, but I think this is causing me a further problem. I've got this working on a button click for the moment, but to resize correctly I have to click the button twice. The first time it resizes but not correctly, then I click it again and it resizes correctly. I have tried a single button click and in the handler calling the method twice but this is the same, it seems to require the interaction of actually clicking the button. Anybody got any ideas? Thanks.
                                  • 14. Re: Autosize Datagrid columns
                                    JericoC
                                    Thanks for the code! However, I get errors when I try to execute the code and I have more columns than are visible on the screen in the Datagrid. Here is the error:

                                    Optimized width of col 14 to 165
                                    TypeError: Error #1010: A term is undefined and has no properties.
                                    at mx.controls::DataGrid/ http://www.adobe.com/2006/flex/mx/internal::resizeColumn()[C:\dev\GMC\sdk\frameworks\mx\co ntrols\DataGrid.as:2379
                                    at mx.controls.dataGridClasses::DataGridColumn/set width()[C:\dev\GMC\sdk\frameworks\mx\controls\dataGridClasses\DataGridColumn.as:1048]
                                    at view.forms::securitysetup/optimizeColumnWidths()[C:\Documents and Settings\Misc\Desktop\MPR\MPRPro\view\forms\securitysetup.mxml:417]
                                    at view.forms::securitysetup/dataHandler()[C:\Documents and Settings\Misc\Desktop\MPR\MPRPro\view\forms\securitysetup.mxml:116]
                                    at view.forms::securitysetup/___Operation1_result()[C:\Documents and Settings\Misc\Desktop\MPR\MPRPro\view\forms\securitysetup.mxml:432]
                                    at flash.events::EventDispatcher/dispatchEventFunction()
                                    at flash.events::EventDispatcher/dispatchEvent()
                                    at mx.rpc::AbstractOperation/ http://www.adobe.com/2006/flex/mx/internal::dispatchRpcEvent()[C:\dev\enterprise_gmc\frame works\mx\rpc\AbstractOperation.as:179
                                    at mx.rpc::AbstractInvoker/ http://www.adobe.com/2006/flex/mx/internal::resultHandler()[C:\dev\enterprise_gmc\framewor ks\mx\rpc\AbstractInvoker.as:167
                                    at mx.rpc::Responder/result()[C:\dev\enterprise_gmc\frameworks\mx\rpc\Responder.as:48]
                                    at mx.rpc::AsyncRequest/acknowledge()[C:\dev\enterprise_gmc\frameworks\mx\rpc\AsyncRequest.a s:82]
                                    at DirectHTTPMessageResponder/completeHandler()[C:\dev\enterprise_gmc\frameworks\mx\messagin g\channels\DirectHTTPChannel.as:359]
                                    at flash.events::EventDispatcher/dispatchEventFunction()
                                    at flash.events::EventDispatcher/dispatchEvent()
                                    at flash.net::URLLoader/onComplete()

                                    It shoots me to the code in the DataGrid.as in the ResizeColumns function and I think the error occurs because the code is trying to resize a column that is not visible in the datagrid (i.e. you have to horizontally scroll to find it).

                                    Here is where it stops in DataGrid.as: if (w < visibleColumns[col].minWidth)

                                    Please help me troubleshoot this because the code is awesome and I really need it to work.

                                    Thanks
                                    • 15. Re: Autosize Datagrid columns
                                      JericoC Level 1
                                      I figured it out.

                                      Apparently, the OptimizeColumnWidths code will only work correctly in Flex 3. I was getting all my bugs when I tried to run it in Flex 2.

                                      Also, be careful when you run the code on a datagrid with lots of data! It can really slow down your app.
                                      • 16. Autosize Datagrid columns
                                        nate-digg
                                        angie_mc-

                                        To resolve the issue of column widths not binding correctly simply set the dg.horizontalScroll = "on" before binding widths and then back to dg.horizontalScroll = "off" once completed.