Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Flex, what's the best way to use a dictionary as a dataprovider?

Normally in Flex you use a collection like ArrayCollection as the dataprovider for components. I often have data stored as a dictionary whose values I would like to use as a dataprovider.

How would you recommend doing this?

like image 222
justkevin Avatar asked Feb 27 '23 13:02

justkevin


2 Answers

The ideal solution is to not use a dictionary but that doesn't answer your question...

So, if you were forced to use dictionaries, one way to tackle this problem would be to use a function as your "middle man." It can go between your dictionary and the Flex components that care about when it changes.

Of course, with large dictionaries, this may be inefficient but in most cases, the performance should be acceptable.

First, you need a function to convert from Dictionary to ArrayCollection. One of the following working examples could suffice:

Extracting Key/Value Collections from a Dictionary

    public function extractKeys(d:Dictionary):ArrayCollection {
        var keyList:ArrayCollection = new ArrayCollection();
        if(d != null) for(var key:* in d) keyList.addItem(key);
        return keyList;
    }

    public function extractValues(d:Dictionary):ArrayCollection {
        var valueList:ArrayCollection = new ArrayCollection();
        if(d != null) for each(var value:* in d) valueList.addItem(value);
        return valueList;
    }

Then, you could actually bind to these functions, themselves! That way, anytime the underlying dictionary is modified, any objects that depend on these functions will get updated. For example:

Binding to Dictionary Values by Using a Function

    private var myDictionary:Dictionary; //initialized and used elsewhere

    [Bindable(event="dictionaryValueChanged")]
    public function extractValues(d:Dictionary):ArrayCollection {
        var valueList:ArrayCollection = new ArrayCollection();
        if(d != null) for each(var value:* in d) valueList.addItem(value);
        return valueList;
    }

    public function updateDictionary(key:Object, value:Object):void {
        myDictionary[key] = value;
        dispatchEvent("dictionaryValueChanged");
    }

From there you can use THE FUNCTION as your dataprovider. As in:

    <mx:DataGrid id="valueGrid" dataProvider="{extractValues()}" />

Whenever your dictionary changes (via the updateDictionary function), it will ultimately trigger an update in the DataGrid!

This is really just an application of a very powerful technique in flex: binding to functions. Once you get the hang of it, there are a wide variety of problems that can be solved with this approach.

I hope that helps someone,

-gMale

EDIT:

I'd have to play around with it but I think you could also eliminate the 'updateDictionary' function by doing something like this, instead:

    [Bindable(event="dictionaryValueChanged")]
    private var myDictionary:Dictionary; //initialized and used elsewhere

    [Bindable(event="dictionaryValueChanged")]
    public function extractValues(d:Dictionary):ArrayCollection {
        var valueList:ArrayCollection = new ArrayCollection();
        if(d != null) for each(var value:* in d) valueList.addItem(value);
        return valueList;
    }
like image 134
gMale Avatar answered Mar 07 '23 22:03

gMale


Other than extending the "dataProvider using" component, or creating a ListCollectionView class that will use a Dictionary as a source; I think you're kind of stuck.

The list based components are designed to display data that comes in some form of order. Dictionary's have no such order.

like image 25
JeffryHouser Avatar answered Mar 07 '23 23:03

JeffryHouser