为了保障原创作者在本站发表文章的利益, 并维护本站原创的精神, 特声明: RIAShanghai对有以下任何情况之一的文章将不通知作者并直接进行快意删除:
- 非原创, 或者原创但一文多发;
- 各种形式的广告与吹擂;
- 不符合本站文章格式.
欢迎各位读者监督. 谢谢合作. 另: 作为Adobe正式的UG, 我们将把Adobe不定期分发的软件,书籍及各种纪念品赠送给发文活跃的作者, 共同进步.
有些objects是无法确定何时被创建的,给这些自动创建的objects传值有一定的挑战。我们假设自动生成的objects为o1, o2, … 其class为O,另外一组可以非自动生成的objects a1, a2, … 对应class为A。目的:我们需要o2来获取a2的reference. 可以考虑的方法有:
- 我们创建一个hash map, 而且此hash map是Singleton, 将a1, a2 …等都放进去,这样在任何地方,都可以通过HashMap.singleton.getA(“2”)类似的方法获取到a2. 实际上这就是设计模式Service Locator的一种典型应用;设计模式并非是万能药,这里使用它有点用牛刀杀鸡的感觉。这里还有一个问题是,要a2来传递”2“给service locator, 此”2“本身也得被传入,所以没有解决根本问题。
- 更多的情况下,自动生成的objects某些methods会被呼叫到或者其属性被设置,这样便打开了通向外界的大门。下面将以DataGrid ItemEditors为例演示此种方法。
下图是一个很典型的例子:当用户在ComboBox里选取新值时,DataGrid中的ItemEditor需要被更新 - 这里用户选择一个Entity, 基于ComboBox实现的ItemEditor需要更新其dataprovider为这个选中Entity的attributes.
实现方法:我们首先把选中的Entity值放到DataGrid.data里 (因为这里DataGrid.data没有用处);然后我们的ItemEditor可以获取到这个DataGrid,及其.data的值,这就实现了传递。
代码:
public class ItemEditorComboAttrs extends ComboBox {
protected var _entity:Entity;
/** Attributes owned by the entity */
public var attributtes:ArrayCollection;
protected var lastOwner:DisplayObjectContainer = null;
protected var watcherDataGridData:ChangeWatcher;
override public function set data(value:Object):void {
if(watcherDataGridData == null || lastOwner != owner) {
if(watcherDataGridData != null) {
watcherDataGridData.unwatch();
}
lastOwner = owner; // 获取DataGrid
watcherDataGridData = BindingUtils.bindSetter(entityChanged, owner, ["data"]);
}
if(_entity != null) {
selectedItem = _entity.getAttributeBySystemName(String(value["targetPath"]));
}
}
// Called when datagrid.data changed.
protected function entityChanged(entity_:Entity):void {
entity = entity_;
}
public function set entity(value:Entity):void {
if(_entity == value) {
return;
}
if(_entity != null) {
dataProvider = null;
}
_entity = value;
if(_entity != null) {
dataProvider = _entity.attributesOwned;
}
}
} // end class
} // end package使用DataGrid.data是一种取巧的做法。追求纯粹的开发者可以通过监听itemEditorBegin event, 更改传到item editors里的data, 异曲同工。
以上实现方法不局限于ActionScript,更适用于包括Java在内的其他语言
上面使用 .data的做法是一种取巧的做法,正式做法应该如下 - 定义专门的property用来传入外面的值:
public class DataGridWithExternalProperty extends DataGrid {
// external property that can be set and used by ItemEditor of cells.
[Bindable]
public var externalProp:Object;
} // end class
...
watcherDataGridData = BindingUtils.bindSetter(entityChanged, owner, ["externalProp"]);在Flex SDK 3.4中,使用.data将导致如下的错误:
TypeError: Error #1010: A term is undefined and has no properties.
at mx.controls.listClasses::ListBase/setSelectionDataLoop()
原因大约是:.data被默认为是选中的元素(在ListBase的subclass List中),而DataGrid里面没有对.data进行特别处理,这样就出现问题了。
使用正式做法不会产生问题。