user120118
user120118

Reputation: 65

Dynamically change the width of Datagrid column in FLEX

Can we change the width of the datagrid column dynamically by clicking on the border of the column in order to display the complete string which is too long to be displayed and needs to be scrolled ? If so, How ?

Also, how can we ensure that the column width changes dynamically based on the number of characters / length of string; since many a times the data is too long to be displayed. Can we set the column width to take the length of data into consideration before displaying onto the datagrid ?

Upvotes: 3

Views: 16268

Answers (4)

Eran Betzalel
Eran Betzalel

Reputation: 4203

I recently encountered that same issue and the only solution I found is to use a customized function that optimizes the DataGrid's columns width as suggested here:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.core.UITextField;
import mx.controls.dataGridClasses.DataGridItemRenderer;

public function optimiseGridColumns(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) {
                                                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) {
                                        // 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)
                                        {
                                                dg.columns[col].width = widths[col];
                                        }
                                }
                        }
                } 

]]>
</mx:Script>
    <mx:XMLList id="employees">
        <employee>
            <name>Christina Coenraets</name>
            <phone>555-219-2270</phone>
            <email>[email protected]</email>
            <active>true</active>
        </employee>
        <employee>
            <name>Joanne Wall</name>
            <phone>555-219-2012</phone>
            <email>[email protected]</email>
            <active>true</active>
        </employee>
        <employee>
            <name>Maurice Smith</name>
            <phone>555-219-2012</phone>
            <email>[email protected]</email>
            <active>false</active>
        </employee>
        <employee>
            <name>Mary Jones</name>
            <phone>555-219-2000</phone>
            <email>[email protected]</email>
            <active>true</active>
        </employee>
    </mx:XMLList>
        <mx:DataGrid id="dg1" width="100%" height="100%" rowCount="5" dataProvider="{employees}" creationComplete="optimiseGridColumns(dg1)">
            <mx:columns>
                <mx:DataGridColumn dataField="name" headerText="Name"/>
                <mx:DataGridColumn dataField="phone" headerText="Phone"/>
                <mx:DataGridColumn dataField="email" headerText="Email"/>
            </mx:columns>
        </mx:DataGrid>

</mx:Application>

Upvotes: 1

Rob Lund
Rob Lund

Reputation: 603

So I was having a similar problem and here is what I found. If you set:

horizontalScrollPolicy="off"

Then the column widths will size automatically to fit the width of the DataGrid. You can also manually set the column widths, as long as scrolling is set to either on or off and not set to auto. I found an interesting article about this, http://junleashed.wordpress.com/2008/07/10/flex-datagridcolumn-width-management/. Basically, he manages the column widths manually, and then calculates whether the scrollbar should be on or off.

Upvotes: 2

user56250
user56250

Reputation:

This is what I came up with however it may not be efficient for large data providers:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
    creationComplete="onComplete();">

    <mx:Script>
        <![CDATA[
            // imports:
            import mx.events.FlexEvent;
            import mx.core.UIComponent;
            import mx.controls.dataGridClasses.DataGridColumn;
            import mx.controls.Text;
            import mx.utils.ObjectUtil;
            import mx.controls.Label;
            import mx.collections.ArrayCollection;
            // data provider:
            [Bindable] private var dp:ArrayCollection = new ArrayCollection();

            private function onComplete():void {
                // populate data provider here
                // to avoid calcMaxLengths execution when the app is created:
                dp = new ArrayCollection(
                    [
                        { col1: "Short", col2: "Other column 1" },
                        { col1: "Some long string", col2: "Other column 2" },
                        { col1: "Short", col2: "Other column 3" },
                        { col1: "Short", col2: "Other column 4" },
                        { col1: "The longest value in this column", col2: "Other column 5" },
                        { col1: "Short", col2: "Other column 6" },
                        { col1: "Short", col2: "Other column 7" }
                    ]
                );
            }

            // this is going to be executed whenever the data provider changes:
            [Bindable("dataChange")]
            private function calcMaxLengths(input:ArrayCollection):ArrayCollection {
                // if there are items in the DP:
                if ( input.length > 0 ) {
                    // and no SPECIAL child exists:
                    if ( getChildByName("$someTempUICToRemoveAfterFinished") == null ) {
                        // create new SPECIAL child
                        // this is required to call measureText
                        // if you use custom data grid item renderer
                        // then create instance of it instead of UIComponent:
                        var uic:UIComponent = new UIComponent();
                        // do not show and do not mess with the sizes:
                        uic.includeInLayout = false;
                        uic.visible = false;
                        // name it to leverage get getChildByName method:
                        uic.name = "$someTempUICToRemoveAfterFinished";
                        // add event listener:
                        uic.addEventListener(FlexEvent.CREATION_COMPLETE, onTempUICCreated);
                        // add to parent:
                        addChild(uic);
                    }
                }
                // return an input:
                return input;
            }

            // called when SPECIAL child is created:
            private function onTempUICCreated(event:FlexEvent):void {
                // keep the ref to the SPECIAL child:
                var renderer:UIComponent = UIComponent(event.target);
                // output - this will contain max size for each column:
                var maxLengths:Object = {};
                // temp variables:
                var key:String = "";
                var i:int=0;
                // for each item in the DP:
                for ( i=0; i<dp.length; i++ ) {
                    var o:Object = dp.getItemAt(i);
                    // for each key in the DP row:
                    for ( key in o ) {
                        // if the output doesn't have current key yet create it and set to 0:
                        if ( !maxLengths.hasOwnProperty(key) ) {
                            maxLengths[key] = 0;
                        }
                        // check if it's simple object (may cause unexpected issues for Boolean):
                        if ( ObjectUtil.isSimple(o[key]) ) {
                            // measure the text:
                            var cellMetrics:TextLineMetrics = renderer.measureText(o[key]+"");
                            // and if the width is greater than longest found up to now:
                            if ( cellMetrics.width > maxLengths[key] ) {
                                // set it as the longest one:
                                maxLengths[key] = cellMetrics.width;
                            }
                        }
                    }
                }

                // apply column sizes:
                for ( key in maxLengths ) {
                    for ( i=0; i<dg.columnCount; i++ ) {
                        // if the column actually exists:
                        if ( DataGridColumn(dg.columns[i]).dataField == key ) {
                            // set size + some constant margin
                            DataGridColumn(dg.columns[i]).width = Number(maxLengths[key]) + 12;
                        }
                    }
                }
                // cleanup:
                removeChild(getChildByName("$someTempUICToRemoveAfterFinished"));
            }

        ]]>
    </mx:Script>

    <mx:DataGrid id="dg" horizontalScrollPolicy="on" dataProvider="{calcMaxLengths(dp)}" width="400">
        <mx:columns>
            <mx:DataGridColumn dataField="col1" width="40" />
            <mx:DataGridColumn dataField="col2" width="100" />
        </mx:columns>
    </mx:DataGrid>

</mx:WindowedApplication>

Upvotes: 1

Cameron
Cameron

Reputation: 340

For the Gridview control, you can drill-down into the SelectedRowStyle property and set Wrap to True.

Upvotes: 0

Related Questions