1
votes

I have a dataGrid in which I use a labelFunction on a column. This changes the dataField to a different value.

I have a sortCompareFunction on the the same column. But, the sortCompareFunction just uses the underlying data items value.

I know I can call the labelFunction from within the sortCompareFunction to change the values before doing a comparison, but what I want to do is: pass the displayed value from the column to the sortCompareFunction. Is this possible.

Some sample code below to represent the problem (works if you copy and past to a new Flex 3 application)

In the image, the data behind the value "AAAAA" is "The Wall", so it appears in the centre when doing a sort, I want access to the "AAAA" value: enter image description here

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"
                initialize="init()">
    <mx:Script>
        <![CDATA[
            import mx.collections.ArrayCollection;
            import mx.controls.dataGridClasses.DataGridColumn;
            import mx.utils.ObjectUtil;

            [Bindable]
            private var albums:ArrayCollection;

            private function init():void
            {
                var album:Object;
                albums = new ArrayCollection();

                album = new Object();
                album.name = "Who's Next";
                album.artist = "The Who";
                album.date = "Jul 31 1971";
                albums.addItem(album);

                album = new Object();
                album.name = "Exile on Main St.";
                album.artist = "The Rolling Stones";
                album.date = "May 12 1972";
                albums.addItem(album);

                album = new Object();
                album.name = "The Wall";
                album.artist = "Pink Floyd";
                album.date = "Dec 8 1979";
                albums.addItem(album);
            }

            private function nameLabelFunction(inData:Object, inColumn:DataGridColumn):String
            {
                if(inData.name == "The Wall")
                {
                    return "AAAA"
                }
                else
                    return inData.name;
            }

            private function nameSortCompare(obj1:Object, obj2:Object):int
            {
                return ObjectUtil.stringCompare(obj1["name"], obj2["name"], true);
            }

        ]]>
    </mx:Script>
    <mx:DataGrid width="400" height="600" dataProvider="{albums}">
        <mx:columns>
            <mx:DataGridColumn dataField="name" headerText="Name" width="125" 
                               labelFunction="nameLabelFunction"
                               sortCompareFunction="nameSortCompare"/>

            <mx:DataGridColumn dataField="artist" headerText="Artist" width="125" />

            <mx:DataGridColumn dataField="date" headerText="Date" width="100" />
        </mx:columns>
    </mx:DataGrid>
</mx:Application>
1
What kind of practical scenario would you like to implement? Two objects are compared according to the field "name" in your compare function and the comparison does not depend on the actual label. Can you explain your aim more specific?Anton
Let's say there is a very heavy process for generating the label in the nameLabelFunction(), I do not want to have to repeat this process thousands of times when sorting a massive dataGrid. I don't know how to get access to the actual 'label'Drenai
In general you can't. Flex doesn't store label values for ALL dataGrid data. Just as you said data can be thousands of items, but DataGrid displays only few. Just think about it and it will be clear that you have to find another approach. If you need further help please comment.David Goshadze
Hey David, yeah, theres no easy way around it. The comments below by Anton were helpful, especially adding the label value to the data object after it's been computed, and then using that. It's a good optionDrenai

1 Answers

1
votes

Can we use a little trick?

        private function nameLabelFunction(inData:Object, inColumn:DataGridColumn):String
        {
            if(inData.name == "The Wall")
            {
                inData.realLabel = 'AAAA';

                return "AAAA"
            }
            else
            {
                inData.realLabel = inData.name;

                return inData.name;
            }
        }

        private function nameSortCompare(obj1:Object, obj2:Object):int
        {
            return ObjectUtil.stringCompare(obj1["realLabel"], obj2["realLabel"], true);
        }

enter image description here

//EDIT

Another approach to use the labelFunction itself

You can use the Function to evaluate the values being compared

Suppose f is an Object of class Function, then

f.call(dg.columns[0], obj1, dg.columns[0])

gives you the actual label of the datagrid field.

//this function should not be changed
        private function nameLabelFunction(inData:Object, inColumn:DataGridColumn):String
        {
            if(inData.name == "The Wall")
                return "AAAA"
            else
                return inData.name;
        }

//the actual comparison looks now like this:
        private function nameSortCompare(obj1:Object, obj2:Object):int
        {
            var f:Function = (dg.columns[0] as DataGridColumn).labelFunction;

            return ObjectUtil.stringCompare(f.call(dg.columns[0], obj1, dg.columns[0]), f.call(dg.columns[0], obj2, dg.columns[0]), true);
        }