...

View Full Version : Update item renderer



byuhobbes85
02-13-2009, 02:02 AM
http://arclite.byu.edu/flex.png

Above is a screenshot of a simple test authoring tool I am creating with Flex. On the left is an editable List control that contains possible responses. On the right is another editable List control that contains test questions. Each test question has a TextInput control to specify the question prompt, and then a ComboBox to specify which of the responses on the left is the correct response for that question.

It took a bit of work to update the itemRenderer on the right when a change was made on the left, but that is working fine now. However, when I add a new question to the List on the right, the ComboBoxes render the first item in their dataProvider, whether or not that item was selected before the new question was added.

I have attached my code. You should be able to just copy, paste, and run. Add a few questions, play with the values in both lists, and then add another question. You will see the weirdness with the ComboBoxes. You can click the "Check Data" button at any time to see the text of each input and selected index of each ComboBox.

Can anyone help me here?

Thanks.


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="650" height="265" backgroundColor="#FFFFFF" backgroundAlpha="0" creationComplete="init()">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.Alert;

[Bindable] private var questionData:ArrayCollection;
[Bindable] private var responseData:ArrayCollection;

private function addQuestion():void {
var newQuestion:Object = new Object();
newQuestion.prompt = "question";
newQuestion.selectedResponse = 0;
newQuestion.responses = responseData;
questionData.addItem(newQuestion);
}

private function checkData():void {
var output:String = "";
for(var iter:int = 0; iter < questionList.dataProvider.length; iter++) {
output += "Prompt: "+ questionList.dataProvider.getItemAt(iter).prompt +", selected response index: "+ questionList.dataProvider.getItemAt(iter).selectedResponse +"\n";
}

Alert.show(output, "Test");
}

private function init():void {
questionData = new ArrayCollection();
responseData = new ArrayCollection();
responseData.addItem("Response a");
responseData.addItem("Response b");
}
]]>
</mx:Script>
<mx:List id="responseList" x="10" y="27" height="47" width="250" editable="true" dataProvider="{responseData}" textAlign="center" itemEditEnd="questionList.itemRenderer = new ClassFactory(questionRenderer);"></mx:List>
<mx:Label y="10" text="Possible Responses" left="10"/>
<mx:List id="questionList" y="27" right="10" width="350" height="200" dataProvider="{questionData}" dragEnabled="true" dropEnabled="true" dragMoveEnabled="true" rendererIsEditor="true">
<mx:itemRenderer>
<mx:Component className="questionRenderer">
<mx:HBox horizontalCenter="0" horizontalAlign="center">
<mx:TextInput id="editorPrompt" text="{data.prompt}" change="data.prompt = editorPrompt.text" textAlign="center" />
<mx:ComboBox id="editorSelectedResponse" width="150" dataProvider="{data.responses}" selectedIndex="{data.selectedResponse}" change="data.selectedResponse = editorSelectedResponse.selectedIndex" />
</mx:HBox>
</mx:Component>
</mx:itemRenderer>
</mx:List>
<mx:Label y="10" text="Test Items" x="290"/>
<mx:Button x="425" y="233" label="Add Question" click="addQuestion()" />
<mx:Button x="10" y="235" label="Check Data" click="checkData()" />

</mx:Application>

byuhobbes85
02-14-2009, 01:40 PM
It turns out that the solution to this problem is to add a call to the List.refresh() method to my code. I had a similar rendering issue with a Tree control before, and I discovered that it could be solved by calling the Tree.validateNow() method. I don't understand a lot of these subtle differences in Flex, but I'm glad I was able to figure things out.

Old function.

private function addQuestion():void {
var newQuestion:Object = new Object();
newQuestion.prompt = "question";
newQuestion.selectedResponse = 0;
newQuestion.responses = responseData;
questionData.addItem(newQuestion);
}

New function.

private function addQuestion():void {
var newQuestion:Object = new Object();
newQuestion.prompt = "question";
newQuestion.selectedResponse = 0;
newQuestion.responses = responseData;
questionData.addItem(newQuestion);
responseData.refresh();
}

byuhobbes85
02-14-2009, 01:44 PM
Correction, .refresh() is not called directly on the List control, but on the ArrayCollection that serves as a data provider to the ComboBoxes in the List control's itemRenderer.



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum