tags:

views:

6897

answers:

7

Hi All

I'm trying to create a datagrid which will resize vertically to ensure all the renderers are displayed in full. Additionally,

  • Renderers are of variable height
  • Renderers can resize themselves

Generally speaking, the flow of events is as follows :

  • One of the item renderers resizes itself (normally in response to a user click etc)
  • It dispatches a bubbling event which the parent datagrid picks up
  • The DataGrid attempts to resize to ensure that all renderers remain visible in full.

I'm currently using this code within the datagrid to calculate the height:

height = measureHeightOfItems(0, dataProvider.length ) + headerHeight;

This appears to get an incorrect height. I've tried a number of variations including callLater ( to ensure the resize has completed so measure can work correctly), and overriding meausre() and calling invalidateSize() / validateSize(), but neither works.

Below are 3 classes which will illustrate the problem. Clicking the button in the item renderers resizes the renderer. The grid should also expand so that all of the 3 renderers are shown in their entirety.

Any suggestions would be greatly appreciated.

Regards

Marty

DataGridProblem.mxml (Application file)

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"
    xmlns:view="view.*">
    <mx:ArrayCollection id="dataProvider">
     <mx:String>Item A</mx:String>
     <mx:String>Item B</mx:String>
     <mx:String>Item C</mx:String>
    </mx:ArrayCollection>
    <view:TestDataGrid
     id="dg" 
     dataProvider="{ dataProvider }"
     width="400">
     <view:columns>
      <mx:DataGridColumn dataField="text" />
      <mx:DataGridColumn itemRenderer="view.RendererButton" />
     </view:columns>
    </view:TestDataGrid>
</mx:Application>

view.TestDataGrid.as

package view
{
    import flash.events.Event;

    import mx.controls.DataGrid;
    import mx.core.ScrollPolicy;

    public class TestDataGrid extends DataGrid
    {
     public function TestDataGrid()
     {
      this.verticalScrollPolicy = ScrollPolicy.OFF;
      this.variableRowHeight = true;
      this.addEventListener( RendererButton.RENDERER_RESIZE , onRendererResize );
     }
     private function onRendererResize( event : Event ) : void
     {
      resizeDatagrid();
     }
     private function resizeDatagrid():void
     {
      height = measureHeightOfItems(0, dataProvider.length ) + headerHeight;
     }
    }
}

view.RendererButton.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml"&gt;
    <mx:Button width="50" height="50"
     click="onClick()" />

    <mx:Script>
     <![CDATA[

      public static const RENDERER_RESIZE : String = "resizeRenderer";
      private function onClick() : void
      {
       this.height += 20;
       dispatchEvent( new Event( RENDERER_RESIZE , true ) );
      }
     ]]>
    </mx:Script>
</mx:HBox>
A: 

Hi,

To do things such as variable width and height cells/rows/column, as well as other "advanced" features - try extending the AdvancedDataGrid rather than the older, more boring DataGrid

adam
HiIn this siuation, using the AdvancedDataGrid is not an option.RegardsMarty
Marty Pitt
A: 

For what it's worth, I never managed to resolve this issue. Code quickly became obsessed with dealing with edge cases.

I ended up throwing out the dataGrid approach, and wrote a solution using VBox & HBox to facilitate resizing.

Marty Pitt
A: 

for what its worth; you were supposed to use the variableRowHeight="true" property of the datagrid / advanced datagrid.

if it makes you feel better i created the custom VBox,HBox solution then after that discovered that its already done!! (snap!!)

good luck!

Hi VusiI'd already tried using variableRowWidth=true, but it didn't solve the problem (as it seems you're now facing)
Marty Pitt
A: 

but now the problem i'm facing is that sometimes the datagrid doesnt seem to calculate the correct height (its a few pixels too small) - the problem is very random;

what method can i use to redraw the control | invalidate()?

HiThe problem here is actually that renderers don't appear to resize themselves after their internal content changes.variableRowWidth=true will allow row sizes to be individually measured and vary once. But, if the row size of the renderer later changes, this isn't re-measured or observed.The problem gets even trickier because renderers are constantly recycled.In short, I didn't find a solution to the problem, instead wrote a simpler implementation that solves less than the dataGrid. I'll post the classes here.
Marty Pitt
A: 

There's an underlying problem to your approach. ItemRenderers are intended to render the data item in a consistent manner, and if you throw out the current renderer and create a new one and set the data property of the new renderer, it should look identical to the previous one. You're not supposed to make transient changes to the renderer outside of the data member, and the renderer is going to behave in odd ways when you do that.

I suspect that if you changed your data model objects to contain a count property and data bound your renderer's height to the expression "{50 + data.count * 20}", and then made the button's click handler increment data.count by 1, that this would work properly. (My experience is that the DataGrid will redraw itself with the proper size for each row as long as the changes get done as a result of the data property, before it calls makeRowsAndColumns(). ) I haven't tried that approach for your example, so I can't say for sure that it actually works, but certainly that's the proper mindset for working with item renderers.

A: 

You can achieve this goal with the AdvancedDataGrid using the following code. If you remove the this.headerHeight, it works for List as well, which makes me believe it should work for the regular old DataGrid.

  override protected function measure():void
  {
   super.measure();

   if ( this.dataProvider )
   {
    var newHeight : int = measureHeightOfItems( 0, this.dataProvider.length ) + this.headerHeight;

    this.minHeight = newHeight;
    this.height = newHeight;
   }
  }
A: 

Hi,
To re size the Data-grid at runtime....use rowcount property and bind it with the dataprovider length. As the dataprovider is updated so will be the rowcount.
You can see the example how to use rowcount in flex here

Hara Chaitanya