views:

283

answers:

1

Can't seem to bind to data from within a custom component. I've tried BindUtilis and {} but can't seem to fathom it out. Here's what I've got:

I have a class DataModel which has been made bindable

Within Mainn.mxml I have two components: DataGrid (used for testing) & CustomComponent (which extends Canvas)

When the data within DataModel.somelist is updated the DataGrid reflects the changes but the CustomComponent doesn't appear to.

I was expecting to see the trace (CustomComponent.dataProvider) fired whenever this._dataModel.itemList is changed. What am I doing wrong?

Main.mxml looks something like this:

<mx:Script>
<![CDATA[
    import model.DataModel;

    [Bindable]
    private var _dataModel:DataModel = DataModel.getInstance();

]]>
</mx:Script>

<mx:VBox width="100%" height="100%">
    <views:ItemDisplayList  width="100%" height="300" id="idl" >
        <views:dataProvider>
            {this._dataModel.itemList}
        </views:dataProvider>
    </views:ItemDisplayList>

    <mx:DataGrid id="dg" width="100%" height="300" >
        <mx:dataProvider>
            {this._dataModel.itemList}
        </mx:dataProvider>
    </mx:DataGrid>
</mx:VBox>

The CustomComponent has this AS class:

package code{

import model.DataModel;
import mx.containers.Canvas;

public class CustomComponent extends Canvas{

    [Bindable]
    private var _dataModel:DataModel = DataModel.getInstance();

    private var _dataProvider:ArrayCollection ;  

    public function CustomComponent(){
        super();
        _dataProvider = new ArrayCollection();
        trace("CustomComponent start");
    }

    public function get dataProvider() : ArrayCollection {
        trace("get dataProvider");
        return _dataProvider;
    }

    public function set dataProvider(value: ArrayCollection) : void {
        trace("set dataProvider");
        this._dataProvider = value;
        invalidateProperties();
        invalidateSize();
        invalidateDisplayList();
        dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
   }

   ...


    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number ) : void{
        trace("updateDisplayList");       
        super.updateDisplayList(unscaledWidth, unscaledHeight);         
    }
}
}
A: 

Are you resetting the dataProvider in your custom component, or by updating you mean adding/removing an item from dataModel.itemList?

If you're adding an item to dataModel.itemList, then your custom component wont update but the DataGrid will. This is because in the DataGrid (maybe it's in the core ListBase component in Flex?), when you set dataProvider, it adds an event listener for CollectionEvent.COLLECTION_CHANGE. When it hears that (when something in your ArrayCollection/IList changes, from remove/add/refresh/etc), it runs a few methods to update the DataGrid's itemRenderers. You'll have to code that manually if you create your own dataProvider property.

If you set the dataProvider explicitly on your custom component (custom.dataProvider = myArrayCollection), it will update. But that's not the most efficient thing to do. I recommend extending one of the List classes that has already implemented a dataProvider property, it's a lot to tackle.

Check out the source for the mx ListBase's dataProvider method to see what they did.

Hope that helps, Lance

viatropos
Thanks Lance. I had a feeling that somewhere a listener was being added, I guess I was hoping that using Bindable or BindUtils it might be automatic. Anyway, I'll follow your advice here and see where it leads me.
Trist