Invalidation resetting ComboBox

Hi,

When using the following custom itemRenderer class, I'm updating another cell in the same row as a ComboBox to reflect a value determined by that ComboBox's selectedItem.  I use the invalidateList method to update the containing DataGrid's display.

This works.

However, the ComboBox selection returns to the default when this happens, although the updated property in the other cell remains (which is correct).

How do I get the ComboBox to retain the selected option?

I've tried using variations of validateNow, invalidateDisplayList, etc and calling from both the itemRenderer itself and the containing DataGrid.  Calling invalidateList from the DataGrid is the only method that properly updates the related cell value; but this also causes the ComboBox to "reset".  I've also tried with and without the prompt property set - this has no effect on the behavior I'm describing.  I've also tried listening to the DataChange event and performing the changeHandler operations there - this has no effect, and in fact I can't even get an Alert to fire on the DataChange except when first instantiating the component.

TYIA
package renderers {
	
	import flash.events.Event;
	import mx.controls.DataGrid;
	import mx.controls.ComboBox;
	import mx.controls.dataGridClasses.*;
	import mx.events.FlexEvent;
	
	public class UOMBox extends ComboBox {		
		
		private function changeHandler(event:Event):void{
			data.unitRate = selectedItem.RATE;
			DataGrid(DataGridListData(listData).owner).invalidateList();
		}
		override public function set data(value:Object):void{
		 	super.data = value;
		 	dataProvider = value.uom;
		}
		public function UOMBox():void{
			prompt = "UOM";
			labelField = "LABEL";
			addEventListener("change", changeHandler, false, 0, true);
		}		
	}
}

Open in new window

LVL 19
moagriusAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

 
mplordCommented:
Oh man, yes I remember the first time I hit this problem, probably one of the trickiest flex 'features' to deal with that I've encountered.
Can't answer it right now, I'll knock up an example over the next 24 hours if you can wait :)
0
 
moagriusAuthor Commented:
no problem - thanks man
0
 
moagriusAuthor Commented:
I found a simple workaround - I just saved the current selectedIndex to a variable, allow the refresh to happen, and set it back to that saved value.

              override public function set data(value:Object):void{
                   var _selectedIndex:int = selectedIndex;
                   super.data = value;
                   dataProvider = value.uom;
                   selectedIndex = _selectedIndex;
            }

still, i'd be interested to see your approach and would be happy to give you the points
0
 
mplordCommented:
Sorry for delay, got tied up with the holidays ;)

After re-reading your question, I realised this is a slightly different problem to what I had first understood.
That said I see your solution is following a line that works for you, however I think this will only work as long as you don't scroll the grid around.

A situation to watch out for is that 'set data' is called not only when the data for the same row is set again following your call to 'invalidateList', but might also be called when you scroll the grid and the itemrenderer gets reused for a different data row.
If that happens, you might be trying to apply the previously selected index to an index which doesn't exist for the new value.uom which becomes the dataprovider for your renderer. Also in the row your data item gets scrolled to, you might lose the selected index, as you'll try to apply a selectedindex from a previous row to the new row. In summary, when you're creating an itemrenderer, you cannot make an assumption that the row it is displaying has not changed on each call to 'set data'.

The only way I find to avoid any problems with state of itemrenderers, is to physically store the state in the underlying data items. So if you need to store selectedIndex state, you'll need to create a property on your data to hold that state. Your itemrenderer needs to also be an itemeditor, so if you change the selectedItem index the index gets written to the data record, and your 'set data' function should always read from the data item to retrieve state.

Any other way will introduce strange happenings which can be hard to debug. If you need to preserve the combo selection for any given row regardless of scrolling etc., treat the selectedindex state as a first-class citizen of the data you're working with.
0

Experts Exchange Solution brought to you by ConnectWise

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
 
moagriusAuthor Commented:
you're right - in fact, overriding the data setter in this turned out to be the source of many issues.  i ended up casting the custom item renderers as instances of ClassFactory, and using the properties property to set the custom ComboBox's dataProvider.

thanks for the input
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.