2.8 动态填充菜单
2.8.1 问题
你想填充并动态改变菜单
2.8.2 解答
用 ActionScript 分配一个 ArrayCollection 或 XMLListCollection 这样的 Collection 对象给 MenuBar 控件的 dataProvider 属性。
2.8.3 讨论
在 Flex 3 里的 MenuBar 控件支持在运行时动态生成菜单项。下面的代码生成一个有 MenuBar 控件的应用,当应用被初始化时,这个 MenuBar 被一个 ArrayCollecton 对象填充。
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
creationComplete="initApp(event)">
<mx:MenuBar id="menu" dataProvider="{menu_dp}"/>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.events.FlexEvent;
[Bindable]
private var menu_dp:ArrayCollection;
private function initApp(evt:FlexEvent):void {
var temp:Array = new Array();
var subNodes:ArrayCollection = new ArrayCollection([{label:"New"},
{label:"Open"},
{label:"Close",enabled:false}]);
temp.push({label:"File",children:subNodes});
temp.push({label:"Edit"});
temp.push({label:"Source"});
subNodes = new ArrayCollection([{label:"50%", type:"radio",roupName:"one"},
{label:"100%", type:"radio", groupName:"one",selected:true},
{label:"150%", type:"radio", groupName:"one"}]);
temp.push({label:"View",children:subNodes});
menu_dp = new ArrayCollection(temp);
}
]]>
</mx:Script>
</mx:Application>
上述代码用 binding 绑定一个名为 menu_dp 的 ArrayCollecton 对象到 MenuBar 组件的 dataProvider 属性。在该应用的 creationComplete 事件发生时, menu_dp 被初始化,并填充菜单项。就像 Flex 里的其它数据驱动组件一样,使用类似 ArrayCollection 或 XMLListCollection 的 Collection 组件,可以确保基础数据的任何变化都会导致控件的显示作相应的刷新。
译者注 : 请将 subNodes 的第二项的 selected 属性改成 toggled 。如 2.7 节所述, toggled 属性才是控制 radio 类型的菜单项是否被选中的。
Collection 组件提供了便利的方法编辑,添加,删除菜单项。为了说明这一点,这个例子在 MenuBar 下添加了一个简单的 Form 组件,让你可以根据他们在 ArrayCollecton 里的索引编辑菜单。
<mx:Form> <mx:FormHeading label="Menu Editor"/> <mx:FormItem label="Menu Index"> <mx:TextInput id="menuIdx" restrict="0-9" text="0" width="20"/> </mx:FormItem> <mx:FormItem label="Sub-Menu Index"> <mx:TextInput id="subMenuIdx" restrict="0-9" width="20"/> </mx:FormItem> <mx:FormItem label="Menu Label"> <mx:TextInput id="label_ti"/> </mx:FormItem> <mx:FormItem> <mx:Button label="Edit" click="editMenu()"/> </mx:FormItem> </mx:Form>
这是一个很基础的 Form ,它的 input 控件可以让你指定数组索引,依此来获取一个特定的菜单项。在 menuIdx 文本框里输入 0 ,并保持 subMenuIdx 为空,则指定 File 菜单的顶级。在 menuIdx 文本框里输入 0 ,在 subMenuIdx 里输入 0 ,则指定 New 子菜单项。
当用户单击 Edit 按钮, editMenu 方法就被调用,这个方法用指定的索引来获取某个菜单项的引用并改变它的标签。请看如下代码:
private function editMenu():void {
var itemToEdit:Object;
try {
itemToEdit = menu_dp.getItemAt(int(menuIdx.text));
if(subMenuIdx.text) {
itemToEdit = itemToEdit.children.getItemAt(int(subMenuIdx.text));
}
itemToEdit.label = label_ti.text;
menu_dp.itemUpdated(itemToEdit);
}
catch(ex:Error){
trace("could not retrieve menu item");
}
}
editMenu 里的代码查找输入 menuIdx 和 subMenuIdx 里的值,依此去寻找一个特定的菜单项,然后用 label_ti 里的值去刷新那个菜单项显示的内容。注意:为了改变菜单的显示,与 MenuBar 关联的 dataProvider 被改变了,然后用 ArrayCollecton 的 itemUpdated 方法来请求刷新菜单显示。在类似这个例子的嵌套数据结构中,调用 itemUpdated 来请求显示刷新很重要。否则,基础数据改变了,但是显示仍然是旧的内容。示例代码中用了一个 try…catch 块来为数组界限做一些基础的错误处理。