Skip navigation
Currently Being Moderated

Autosize Datagrid columns

Dec 6, 2006 7:09 PM

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?
 
Replies
  • Currently Being Moderated
    Dec 7, 2006 9:54 AM   in reply to jkPatrick05
    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;
    }
     
    |
    Mark as:
  • Currently Being Moderated
    Dec 7, 2006 10:09 AM   in reply to jkPatrick05
    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.
     
    |
    Mark as:
  • Currently Being Moderated
    Dec 7, 2006 10:34 AM   in reply to jkPatrick05
    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;
    }
     
    |
    Mark as:
  • Currently Being Moderated
    Feb 6, 2007 5:16 AM   in reply to michael_ramirez44
    sorry, I'm brand new to flex. How do I use this function on the datagrid?
    thanks
     
    |
    Mark as:
  • Currently Being Moderated
    Feb 6, 2007 1:34 PM   in reply to jakelove007
    By column: dgColumn is you DataGridColumn

    dgColumn.labelFunction = columnText;

    By grid: dg is your DataGrid

    dg.labelFunction = columnText;
     
    |
    Mark as:
  • Currently Being Moderated
    Feb 11, 2007 11:24 PM   in reply to michael_ramirez44
    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
     
    |
    Mark as:
  • Currently Being Moderated
    May 31, 2007 10:30 PM   in reply to arrowCai
    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?
     
    |
    Mark as:
  • Currently Being Moderated
    Jun 23, 2007 10:01 AM   in reply to jkPatrick05
    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];
    }
    }
    }
    }
     
    |
    Mark as:
  • Currently Being Moderated
    Jul 25, 2007 6:30 AM   in reply to JCFlex2
    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
     
    |
    Mark as:
  • Currently Being Moderated
    Jul 30, 2007 7:48 PM   in reply to Sjoerd_
    Dude, create a text field, fill it with the longest string and measure its length.
     
    |
    Mark as:
  • Currently Being Moderated
    Dec 18, 2007 7:06 AM   in reply to Sjoerd_
    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?
     
    |
    Mark as:
  • Currently Being Moderated
    Apr 3, 2008 6:04 PM   in reply to RobX82
    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.
     
    |
    Mark as:
  • Currently Being Moderated
    Apr 30, 2008 3:49 AM   in reply to chris12296
    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.
     
    |
    Mark as:
  • Currently Being Moderated
    Jul 8, 2008 3:38 PM   in reply to JCFlex2
    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\controls\DataGrid.as:2379
    at mx.controls.dataGridClasses::DataGridColumn/set width()[C:\dev\GMC\sdk\frameworks\mx\controls\dataGridClasses\DataGri dColumn.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\frameworks\mx\rpc\AbstractOperation.as:179
    at mx.rpc::AbstractInvoker/ http://www.adobe.com/2006/flex/mx/internal::resultHandler()[C:\dev\ent erprise_gmc\frameworks\mx\rpc\AbstractInvoker.as:167
    at mx.rpc::Responder/result()[C:\dev\enterprise_gmc\frameworks\mx\rpc\Re sponder.as:48]
    at mx.rpc::AsyncRequest/acknowledge()[C:\dev\enterprise_gmc\frameworks\m x\rpc\AsyncRequest.as:82]
    at DirectHTTPMessageResponder/completeHandler()[C:\dev\enterprise_gmc\fr ameworks\mx\messaging\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
     
    |
    Mark as:
  • Currently Being Moderated
    Aug 1, 2008 9:48 AM   in reply to jkPatrick05
    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.
     
    |
    Mark as:
  • Currently Being Moderated
    Dec 3, 2008 11:53 AM   in reply to jkPatrick05
    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.

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)