首页 > 设计 > WEB开发 > 正文

7.5.创建一个Item Editor,它可以处理含有复杂数据类型的Data

2023-08-02 23:09:31
字体:
来源:转载
供稿:网友
7.5.1.问题
如果item editor 收到的data 是一个用户自定义对象,我们需要创建一个可以修改这个含有复杂类型对象的item editor。
7.5.2.解决办法
创建一个item editor,它可以返回data 中所有己经被修改过的属性。在List 上创建一个监听器,用于对itemEditEnd 事件的监听,在收到这个事件后要停止这个事件继续上父级派发(flex 冒泡的事件机制),并读取那个被修改过的item editor 中的data 属性。
7.5.3.讨论
List 类里有一个属性叫editorDataField,如果你的editor 处理的是单个属性,使用它将是最简单最方便的选择.但如果想用editor 处理含有多个属性的复杂对象,必须能够阻止List 、

DataGridColumn 的一些原有动作和事件,并且可以通过itemEditorInstance 读到List、DataGridColumn 中的数据。

在下边的例子中,processData 这个方法是用于处理itemEditEnd 事件的。
+展开
-XML
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxmlwidth="700height="300">
<mx:Script>
<![CDATA[
import mx.events.ListEvent;
import mx.collections.ArrayCollection;
import oreilly.cookbook.MultipleDataTypeEditor;
[Bindable]
Private var arr:ArrayCollection = new ArrayCollection([{age:12, name:"Joe"},{age:16,name:"Jorge"},{age:19, name:"Jojo"}
,{age:2, name:"James"},{age:12, name:"Joaquin"}]);
public function processData(event:ListEvent):void {
// Disable copying data back to the control.
event.preventDefault();
// Get new label from editor.
list.editedItemRenderer.data= MultipleDataTypeEditor
(list.itemEditorInstance).data;
// Close the cell editor.
list.destroyItemEditor();
// Notify the list control to update its display.
list.dataProvider.notifyItemUpdate(list.editedItemRenderer);
}

]]>
</mx:Script>
<mx:List id="listitemEditor="oreilly.cookbook.MultipleDataTypeEditor"
dataProvider="{arr}itemEditEnd="processData(event)"
itemRenderer="oreilly.cookbook.MultipleDataTypeRenderer"
width="350editable="true">

</mx:List>
</mx:Canvas>

Event 的preventDefault 方法,是用于终止Event 中的默认动作,在这里我们用这个方法终止了itemEditor 的默认动作,不再去试图从itemEditor 里读取text 属性。取而带之的是从itemRendererInstance 里得到data 赋值给editedItemRenderers 的data。最后调用List dataProvider 的notifyItemUpdate 方法,从而把用户的修改保存到List 的数据源中(dataProvider)。

上边代码中用到的itemEditor,在get data 方法中只是返回了两个TextInput 的text 属性,即用户的输入值。这个itemEditor 的代码如下:
+展开
-ActionScript
package oreilly.cookbook {
import mx.containers.Canvas;
import mx.controls.TextInput;
public class MultipleDataTypeEditor extends Canvas {
private var nameField:TextInput;
private var ageField:TextInput;
public function MultipleDataTypeEditor() {
super();
nameField = new TextInput();
ageField = new TextInput();
addChild(nameField);
nameField.focusEnabled = false;
addChild(ageField);
ageField.focusEnabled = false;
ageField.x = 100;
this.horizontalScrollPolicy = "none";
}
override public function set data(value:Object):void {
super.data = value;
nameField.text = value.name;
ageField.text = value.age;
}
override public function get data():Object {
return {name:nameField.text, age:ageField.text};
}
}
}

(译者注)
原文译到这儿本节就己经结束了,如果你对item editor 、item renderer 理解的还算深刻,我想你应该很容易理解本节的内容,如果你对item editor 、item renderer 了解的还不够深入,您看完这一节,可能会有些糊涂,我想作者的用意就是想蜻蜓点水的把所有东西都讲给我们,读者再根据自己情况,深入学习。即然我翻译它,目地就是让大家能看明白,话不多说,我再用自己的语言给本节做个总结:

? 1 如果你只是想实现最简单的editor(下面的例子都是以DataGrid 为例)用户点击就进入修改状态,失去焦点就结束修改。(每个单元格只对应data 中的一个单一属性)只需:
+展开
-XML
<mx:DataGrid id="myGrid"dataProvider="{initDG}editable="true">
<mx:columns>
<mx:DataGridColumn dataField="Companyeditable="false"/>
<mx:DataGridColumn dataField="Contact"/>

关键在于DataGrid 中的editable="true" 这样表格中所有单元格都可以修改,如果你想使某一列不可被修改,则editable="false"。

? 2 再复杂一些,如果你有了一个复杂的editor 如:你想用NumericStepper 来修改数值,这样做是很常用的,因为默认的editor 是label ,很不友好。(当然这种情况还只是每个单元格只对应data 中的一个单一属性。)这个时候你要用到DataGridColumn 中的editorDataField 属性,如:
+展开
-XML
<mx:DataGridColumn dataField="quantityeditorDataField="value">
<mx:itemEditor>
<mx:Component>
<mx:NumericStepper maximum="100stepSize="10"/>
</mx:Component>
</mx:itemEditor>
</mx:DataGridColumn>

editorDataField 此属性的用意是:当用户修改完毕,系统并不知道去editor 的哪个属性里取用户修改后的值,因为默认editor 是在text 属生里取,如果你自定义了editor,系统还会去text 里取,没办法,flex 还没有那么智能化,所以您必告诉系统要去NumericStepper的哪个属性里去取用户修改过的值。

如果大家试运行过editor,大家会发现,用户的每次修改都会直接修改dataprovider 中的值,这一点大家一定要注意,因为有些时候,这并不是我们想要的。

通过以上两种情况的说明,大家要知道,看似很简单的操作,实际上系统做了很多工作:
1) 用户没有点击时使用item renderer 显示数据,
2) 用户点击后就item editor 修改数据
3) 用户修改完毕,销毁item editor 再用item renderer 显示数据
4) 用户修改完毕后要找到新的数据,并更新到dataprovider 中去
以上两种情况不管简单还是复杂,都有以上这几步操作的体现,只是大多数工作由系统完成。

? 3 说了这么多,这种情况才是本节讲的重点。一个单元格里有多个属性对应,这种情况上边两种办法都帮不上忙,这时我们要推翻原有的系统工作机制,自己完成上边说的四个工作。其中第一项工作,系统己经帮我们完成了,剩下的三项工作全部在下边方法中完成:
+展开
-ActionScript
public function processData(event:ListEvent):void {
event.preventDefault();
list.editedItemRenderer.data =
MultipleDataTypeEditor(list.itemEditorInstance).data;
list.destroyItemEditor();
list.dataProvider.notifyItemUpdate(list.editedItemRenderer);
}

event.preventDefault();的目地是停止原有动作,这样我们就可以自己去做剩下的三项工作了。

list.editedItemRenderer , 每个List 或dataGrid 都有这个属性,在itemEditBegin 、itemEditEnd这两个事件发生时,你可以通过这个属性的data 得到当前editor 中的值。但默认情况下只会得到一个String , 所以在例子中把修改过的两个属性以对象的形式传到data 中。

list.dataProvider.notifyItemUpdate(list.editedItemRenderer); 把修改过的数据保存在了dataprovider 中.

list.destroyItemEditor();是用于去掉item editor 的显示。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表