The datagrid is organized as follows:

DataGrid (listOwner) >>
   N DataGridRows (Owner is the DataGridRow)
        N CellRenderers (One for each column)

The concept of columns is actually at the DataGridRow level within the MC
hierarchy at runtime. 

Dispatching events is one of the hidden secrets of using V2. When you know
what events to fire where, you can be quite dangerous. This is especially
true using the undocumented DataProvider events. I have solved more data
puzzles through events. It feels like hackery but it is how the system
actually works internally. Dispatching events provides for a much simpler
app as things update themselves as designed. Trying to update all the pieces
manually is madness.

Here is a jewel from the DataProvider Event API. This allows you to refresh
a single row of any control using a dataprovider, from the dataprovider
without knowing the control instance. Basically updateViews broadcasts
events to the subscribed controls. Whatever control(s) are using this
DataProvider will update their view for index 2.

MydataProvider.updateViews( 'updateItem' , 2 )

Pretty cool, eh! :)

Extending DataGridColumn is confusing since you are really working with a
node within the DataGrid.columns array. The CellRenderer API depends on this
structure when rows are being laid out. The only thing that would be useful
here is the ability to shove extra data into the Array node specifically
events you need to listen to.

I wrote a cellRenderer that looked up event data within the DataGrid.columns
array. The cellRenderer would add the function instance that sits in the
DataGrid.columns[N] column data when the cell was instanciated. This way you
could set an event on the column, and your cell Renderer could pick it up.

I do something non-standard with CellRenderer. If you create instances
within createChildren, the DataGrid performance is much worse because the
DataGrid spends its time overwriting cells with new control instances.
Ideally you only want to createChild once and update the view when the data
changes. I accomplish this by  instanciating inner components within
setValue not createChildren. In several cases I have seen pretty large
performance gains in doing things this way. The cellRenderer drag is related
to the isntanciation time of creating inner controls every time anything
moves over the datagrid. This is a huge waste of player energy.

function setValue( str:String , item:Object , sel:Boolean ) {
                
        //instanciate a cell only once and only if data is present!     
        if( ! com && item != undefined ){                       

                //add my TextInput Control in there.
                com = createObject( "TextInput" , "com" , 1 )

                //listen for change and fire a function stored in the column
 com.addEventListener( "change" , mx.util.Delagate.create( com ,
listOwner.getColumnAt( this.getCellIndex().columnIndex ).change  ) )

                size()                  

        }
}

You will need a custom DataGrid Column object to get the change event stored
within the object. Although I think you have this done already.

Hope that helps.

Ted ;)






> -----Original Message-----
> From: [email protected] [mailto:[EMAIL PROTECTED] On
> Behalf Of mrmcfeely8
> Sent: Monday, July 11, 2005 9:49 AM
> To: [email protected]
> Subject: [flexcoders] Re: Extending DataGridColumn + emitting events =
> java.lang.NullPointerException
> 
> Ah!  Now we're getting closer!  I was hoping my little "challenge"
> would evoke a response :)  Thanks, Ted!
> 
> I'm actually already using all those members of the CellRenderer API
> to relay events out to my custom DataGridColumn, but I hadn't thought
> of dispatching the events from the DataGrid itself.  I'll give that a
> try... it definitely seems like the next best alternative.  There are
> a couple drawbacks to that approach, though, that I'd like to get
> around:
> 
> 1) Assuming I use the same CellRenderer for multiple columns in my
> DataGrid, my event handler would have to have a few conditional
> statements to detect which column the event applies to.  Can't say I'm
> a big fan of long if/else or switch statements... or maybe I'm being
> too picky.
> 
> 2) I don't think I'd be able to use this kind of syntax:
>     <mx:DataGrid cellEdit="myEventHandler(event)" ... >
> I'd rather not have to write out a bunch of explicit addEventHandler()
> statements.  I know it's just syntactic sugar, but I do have quite a
> sweet tooth.
> 
> I'd also rather not extend DataGrid and define a bunch of events with
> [Event()] metadata tags (which would enable the type of syntax
> above)... at the DataGrid level, it's hard to tell exactly which
> events will be dispatched from its cells, since the number and type of
> columns is variable... to me, it makes more sense to declare these
> events at the DataGridColumn level, which knows exactly what events it
> dispatches (based on its Cell Renderer).
> 
> Am I wrong to think that emitting events from a custom DataGridColumn
> object should be possible?
> 
> --- In [email protected], "Theodore E Patrick" <[EMAIL PROTECTED]>
> wrote:
> > Use a cellrenderer, the cellRenderer API was designed to extends and
> provide
> > custom inner layout of datagrid cells.
> >
> > There are some default objects that decorate each CellRenederer
> instance:
> >
> >             var listOwner:MovieClip //the datagrid
> >             var getCellIndex:Function
> >             var getDataLabel:Function
> >             var owner:MovieClip //the dataGridColumn instance
> >
> > These are actually present whether you use a customCellRenderer or
> not. So
> > in your case simply use these to listen/dispatch the events you
> need. Your
> > Cellrenderer can add events onto these objects or broadcast events
> out to
> > the DataGrid as things happen within the CellRenderer.
> >
> > For example say I have an inner checkbox within my CellRenderer. I
> would add
> > a click event onto that control where it would do something like
> so.
> >
> > Note: 'com' is my cellRenderers inner component instance:
> >
> > function click(){
> >
> > //obtain the index
> >
> > var index = getCellIndex()
> >
> > //obtain the columnName from the Datagrid
> >
> > var colName = listOwner.getColumnAt( index.columnIndex ).columnName
> >
> > //edit the data because the component data had changed
> >
> > listOwner.dataProvider.editField( index.itemIndex , colName ,
> com.selected )
> >
> > //set the dataproviders seletedIndex
> >
> > listOwner.selectedIndex = index.itemIndex
> >
> > //trigger a 'celledit' event in the datagrid
> >
> > listOwner.dispatchEvent( { type:"cellEdit" , cell:this ,
> column:colName,
> > value:com.selected } )
> >
> > }
> >
> > Stump Flexcoders? Think again! :)
> >
> > Cheers,
> >
> > Ted ;)
> >
> >
> > > Well, I found you can simply pass a Function object to the custom
> > > DataGridCell and have the custom cell handle its own click method
> with
> > > that Function.  The drawback is that the function must live in the
> > > same MXML file that the DataGridCell is declared in.  I'd still
> much
> > > rather use Flex's own event handling mechanisms.  Any other ideas?
> > > Have I stumped the flexcoders?!
> 
> 
> 
> 
> --
> Flexcoders Mailing List
> FAQ: http://groups.yahoo.com/group/flexcoders/files/flexcodersFAQ.txt
> Search Archives: http://www.mail-archive.com/flexcoders%40yahoogroups.com
> Yahoo! Groups Links
> 
> 
> 
> 




--
Flexcoders Mailing List
FAQ: http://groups.yahoo.com/group/flexcoders/files/flexcodersFAQ.txt
Search Archives: http://www.mail-archive.com/flexcoders%40yahoogroups.com 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/flexcoders/

<*> To unsubscribe from this group, send an email to:
    [EMAIL PROTECTED]

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 


Reply via email to